@posthog/wizard 2.10.4 → 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 (90) hide show
  1. package/README.md +48 -7
  2. package/dist/{McpScreen-LqnNwEfV.js → AuditChecksViewer-DsfXIO9e.js} +475 -36
  3. package/dist/AuditChecksViewer-DsfXIO9e.js.map +1 -0
  4. package/dist/{add-mcp-server-to-clients-lfUH2pdU.js → add-mcp-server-to-clients-BKoew3aT.js} +157 -125
  5. package/dist/add-mcp-server-to-clients-BKoew3aT.js.map +1 -0
  6. package/dist/{readiness-Cep84RsR.js → agent-interface-D5W9BAB2.js} +329 -464
  7. package/dist/agent-interface-D5W9BAB2.js.map +1 -0
  8. package/dist/{agent-runner-DHtcWn15.js → agent-runner-B8Cx6X6x.js} +22 -31
  9. package/dist/agent-runner-B8Cx6X6x.js.map +1 -0
  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 +521 -46
  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-CIyf0ZGx.js → debug-I5sRZubJ.js} +1 -1
  18. package/dist/{defaults-DoVkE0gW.js → defaults-GbLPuHxj.js} +8 -8
  19. package/dist/defaults-GbLPuHxj.js.map +1 -0
  20. package/dist/detection-C_RfYYDe.js +206 -0
  21. package/dist/detection-C_RfYYDe.js.map +1 -0
  22. package/dist/{env-api-key-K8TdTDII.js → env-api-key-D5G2PrXW.js} +1 -1
  23. package/dist/{env-api-key-K8TdTDII.js.map → env-api-key-D5G2PrXW.js.map} +1 -1
  24. package/dist/file-8iNrXHkG.js +16 -0
  25. package/dist/file-8iNrXHkG.js.map +1 -0
  26. package/dist/{file-utils-BWneZy6p.js → file-utils-DnTSiTJw.js} +1 -1
  27. package/dist/{file-utils-BWneZy6p.js.map → file-utils-DnTSiTJw.js.map} +1 -1
  28. package/dist/package-json-BzVey4Bd.js +2 -0
  29. package/dist/{package-json-Ctq6LSl8.js → package-json-F_7oktsp.js} +1 -1
  30. package/dist/{package-json-Ctq6LSl8.js.map → package-json-F_7oktsp.js.map} +1 -1
  31. package/dist/{package-manager-CwU26DwX.js → package-manager-qxP2PpM_.js} +2 -2
  32. package/dist/{package-manager-CwU26DwX.js.map → package-manager-qxP2PpM_.js.map} +1 -1
  33. package/dist/paths-DJS47p5x.js +26 -0
  34. package/dist/paths-DJS47p5x.js.map +1 -0
  35. package/dist/{posthog-integration-HBDZrREG.js → posthog-integration-DX77Msto.js} +43 -14
  36. package/dist/posthog-integration-DX77Msto.js.map +1 -0
  37. package/dist/posthog-vm0k9PKS.js +11 -0
  38. package/dist/posthog-vm0k9PKS.js.map +1 -0
  39. package/dist/provisioning-CHfTOEvg.js +2 -0
  40. package/dist/provisioning-DUj285NO.js +166 -0
  41. package/dist/provisioning-DUj285NO.js.map +1 -0
  42. package/dist/{registry-BIV1wRpo.js → registry-CCtIsqb8.js} +5 -6
  43. package/dist/{registry-BIV1wRpo.js.map → registry-CCtIsqb8.js.map} +1 -1
  44. package/dist/{router-CXjdWNh2.js → router-BTfmEDDJ.js} +4 -3
  45. package/dist/router-BTfmEDDJ.js.map +1 -0
  46. package/dist/{setup-utils-CHojnr4N.js → setup-utils-Bv8z6HMb.js} +17 -150
  47. package/dist/setup-utils-Bv8z6HMb.js.map +1 -0
  48. package/dist/setup-utils-CoX-vLgw.js +2 -0
  49. package/dist/{start-playground-D1iLBvqF.js → start-playground-DYNQ8rOz.js} +181 -9
  50. package/dist/start-playground-DYNQ8rOz.js.map +1 -0
  51. package/dist/{start-tui-DkT_H5zx.js → start-tui-DleQG3La.js} +1290 -163
  52. package/dist/start-tui-DleQG3La.js.map +1 -0
  53. package/dist/{steps-zpqG7W08.js → steps-C-syS8if.js} +8 -8
  54. package/dist/steps-C-syS8if.js.map +1 -0
  55. package/dist/task-stream-CX7Uf6EM.js +61 -0
  56. package/dist/task-stream-CX7Uf6EM.js.map +1 -0
  57. package/dist/{telemetry-CPoSyK0a.js → telemetry-DHZfjgqx.js} +2 -2
  58. package/dist/{telemetry-CPoSyK0a.js.map → telemetry-DHZfjgqx.js.map} +1 -1
  59. package/dist/{wizard-abort-BcEPhAxY.js → wizard-abort-DIhFXJ5N.js} +1 -1
  60. package/dist/{wizard-abort-DKctLd33.js → wizard-abort-DfhWuzaw.js} +6 -4
  61. package/dist/{wizard-abort-DKctLd33.js.map → wizard-abort-DfhWuzaw.js.map} +1 -1
  62. package/dist/wizard-session-BQC9vy9Z.js +2 -0
  63. package/dist/{wizard-session-Db6R023m.js → wizard-session-BcNJTl2I.js} +1 -1
  64. package/dist/{wizard-session-Db6R023m.js.map → wizard-session-BcNJTl2I.js.map} +1 -1
  65. package/dist/wizard-ui-YdGFRyu_.js +14 -0
  66. package/dist/wizard-ui-YdGFRyu_.js.map +1 -0
  67. package/npm-shrinkwrap.json +2 -2
  68. package/package.json +1 -1
  69. package/dist/McpScreen-LqnNwEfV.js.map +0 -1
  70. package/dist/add-mcp-server-to-clients-lfUH2pdU.js.map +0 -1
  71. package/dist/agent-runner-DHtcWn15.js.map +0 -1
  72. package/dist/agent-skill-BVjJqol6.js +0 -59
  73. package/dist/agent-skill-BVjJqol6.js.map +0 -1
  74. package/dist/analytics-Cm6i5_gc.js +0 -207
  75. package/dist/analytics-Cm6i5_gc.js.map +0 -1
  76. package/dist/analytics-CviQ_A9M.js +0 -2
  77. package/dist/debug-CyJ_3dTP.js +0 -201
  78. package/dist/debug-CyJ_3dTP.js.map +0 -1
  79. package/dist/defaults-DoVkE0gW.js.map +0 -1
  80. package/dist/detection-gcQwPKPu.js +0 -122
  81. package/dist/detection-gcQwPKPu.js.map +0 -1
  82. package/dist/package-json-BQgl5C3Z.js +0 -2
  83. package/dist/posthog-integration-HBDZrREG.js.map +0 -1
  84. package/dist/readiness-Cep84RsR.js.map +0 -1
  85. package/dist/router-CXjdWNh2.js.map +0 -1
  86. package/dist/setup-utils-CHojnr4N.js.map +0 -1
  87. package/dist/start-playground-D1iLBvqF.js.map +0 -1
  88. package/dist/start-tui-DkT_H5zx.js.map +0 -1
  89. package/dist/steps-zpqG7W08.js.map +0 -1
  90. package/dist/wizard-session-y7nf6aKH.js +0 -2
@@ -1,9 +1,10 @@
1
1
  import { n as __require } from "./rolldown-runtime-B_-DWIq7.js";
2
- import { a as getLogFilePath, c as getUI, o as initLogFile, r as debug, s as logToFile } from "./debug-CyJ_3dTP.js";
3
- import { C as WIZARD_VARIANT_FLAG_KEY, S as WIZARD_VARIANTS, b as WIZARD_REMARK_EVENT_NAME, h as POSTHOG_PROPERTY_HEADER_PREFIX, n as analytics, p as POSTHOG_FLAG_HEADER_PREFIX, v as REMOTE_SKILLS_BASE_URL, x as WIZARD_USER_AGENT } from "./analytics-Cm6i5_gc.js";
4
- import { o as getLlmGatewayUrlFromHost } from "./setup-utils-CHojnr4N.js";
5
- import { n as ADDITIONAL_FEATURE_PROMPTS } from "./wizard-session-Db6R023m.js";
6
- import { n as registerCleanup, r as wizardAbort, t as WizardError } from "./wizard-abort-DKctLd33.js";
2
+ import { A as POSTHOG_PROPERTY_HEADER_PREFIX, B as WIZARD_VARIANTS, L as WIZARD_REMARK_EVENT_NAME, O as POSTHOG_FLAG_HEADER_PREFIX, V as WIZARD_VARIANT_FLAG_KEY, a as getLogFilePath, c as getUI, o as initLogFile, r as debug, s as logToFile, z as WIZARD_USER_AGENT } from "./debug-Bkaqv1ab.js";
3
+ import { i as WIZARD_YARA_REPORT_FILE, o as skillTmpPath } from "./paths-DJS47p5x.js";
4
+ import { n as analytics } from "./analytics-DmD31Ssc.js";
5
+ import { f as getLlmGatewayUrlFromHost } from "./setup-utils-Bv8z6HMb.js";
6
+ import { n as ADDITIONAL_FEATURE_PROMPTS } from "./wizard-session-BcNJTl2I.js";
7
+ import { n as registerCleanup, r as wizardAbort, t as WizardError } from "./wizard-abort-DfhWuzaw.js";
7
8
  import * as fs$1 from "fs";
8
9
  import fs from "fs";
9
10
  import path from "path";
@@ -174,6 +175,49 @@ const LINTING_TOOLS = [
174
175
  "yamllint"
175
176
  ];
176
177
  //#endregion
178
+ //#region src/lib/workflows/audit/types.ts
179
+ /** Single source of truth for status glyph + color across audit views. */
180
+ const AUDIT_SEVERITY_STYLE = {
181
+ pending: {
182
+ glyph: "◌",
183
+ color: "gray"
184
+ },
185
+ pass: {
186
+ glyph: "✔",
187
+ color: "green"
188
+ },
189
+ error: {
190
+ glyph: "✘",
191
+ color: "red"
192
+ },
193
+ warning: {
194
+ glyph: "⚠",
195
+ color: "yellow"
196
+ },
197
+ suggestion: {
198
+ glyph: "•",
199
+ color: "cyan"
200
+ }
201
+ };
202
+ const AUDIT_CHECKS_FILE = ".posthog-audit-checks.json";
203
+ const AUDIT_REPORT_FILE = "posthog-audit-report.md";
204
+ const AUDIT_CHECKS_KEY = "auditChecks";
205
+ function getAuditChecks(session) {
206
+ const raw = session.frameworkContext[AUDIT_CHECKS_KEY];
207
+ return Array.isArray(raw) ? raw : [];
208
+ }
209
+ /**
210
+ * Read the audit checks ledger off disk. Validation lives at write time —
211
+ * every writer (`audit_seed_checks` / `audit_add_checks` / `audit_resolve_checks`
212
+ * MCP tools, `seedAuditLedger`) zod-parses entries before the atomic write,
213
+ * so by the time the file watcher fires we trust the shape and only guard
214
+ * against the file not being a JSON array (corrupted / hand-edited / not yet
215
+ * seeded).
216
+ */
217
+ function coerceAuditChecks(parsed) {
218
+ return Array.isArray(parsed) ? parsed : [];
219
+ }
220
+ //#endregion
177
221
  //#region src/lib/wizard-tools.ts
178
222
  /**
179
223
  * Unified in-process MCP server for the PostHog wizard.
@@ -182,6 +226,8 @@ const LINTING_TOOLS = [
182
226
  * - check_env_keys: Check which env var keys exist in a .env file
183
227
  * - set_env_values: Create/update env vars in a .env file
184
228
  * - detect_package_manager: Detect the project's package manager(s)
229
+ * - load_skill_menu / install_skill: Skill installation
230
+ * - audit_seed_checks / audit_add_checks / audit_resolve_checks: Audit ledger ownership
185
231
  */
186
232
  let _sdkModule$1 = null;
187
233
  async function getSDKModule$1() {
@@ -216,7 +262,7 @@ async function fetchSkillMenu(skillsBaseUrl) {
216
262
  */
217
263
  function downloadSkill(skillEntry, installDir, skillsRoot) {
218
264
  const skillDir = skillsRoot ? path.join(installDir, skillsRoot, skillEntry.id) : path.join(installDir, ".claude", "skills", skillEntry.id);
219
- const tmpFile = `/tmp/posthog-skill-${skillEntry.id}.zip`;
265
+ const tmpFile = skillTmpPath(skillEntry.id);
220
266
  try {
221
267
  fs.mkdirSync(skillDir, { recursive: true });
222
268
  execFileSync("curl", [
@@ -231,6 +277,7 @@ function downloadSkill(skillEntry, installDir, skillsRoot) {
231
277
  "-d",
232
278
  skillDir
233
279
  ], { timeout: 3e4 });
280
+ fs.writeFileSync(path.join(skillDir, ".posthog-wizard"), "");
234
281
  try {
235
282
  fs.unlinkSync(tmpFile);
236
283
  } catch {}
@@ -320,6 +367,122 @@ function mergeEnvValues(content, values) {
320
367
  }
321
368
  return result;
322
369
  }
370
+ const AUDIT_STATUSES = [
371
+ "pending",
372
+ "pass",
373
+ "error",
374
+ "warning",
375
+ "suggestion"
376
+ ];
377
+ const auditCheckSchema = z.object({
378
+ id: z.string().min(1),
379
+ area: z.string().min(1),
380
+ label: z.string().min(1),
381
+ status: z.enum(AUDIT_STATUSES),
382
+ file: z.string().optional(),
383
+ details: z.string().optional()
384
+ });
385
+ const auditUpdateSchema = z.object({
386
+ id: z.string().min(1),
387
+ status: z.enum(AUDIT_STATUSES),
388
+ file: z.string().optional(),
389
+ details: z.string().optional()
390
+ });
391
+ /**
392
+ * Atomically write JSON: write to .tmp then rename. The rename is what bumps
393
+ * the file's mtime, which is what the UI's file watcher polls on.
394
+ */
395
+ function writeLedgerAtomic(targetPath, checks) {
396
+ const tmpPath = `${targetPath}.tmp`;
397
+ fs.writeFileSync(tmpPath, JSON.stringify(checks, null, 2), "utf8");
398
+ fs.renameSync(tmpPath, targetPath);
399
+ }
400
+ /**
401
+ * Apply a batch of patches to the ledger by id. Returns the new array and the
402
+ * list of update ids that didn't match any existing check.
403
+ */
404
+ function applyAuditUpdates(current, updates) {
405
+ const byId = new Map(current.map((c) => [c.id, c]));
406
+ const unknown = [];
407
+ for (const u of updates) {
408
+ const existing = byId.get(u.id);
409
+ if (!existing) {
410
+ unknown.push(u.id);
411
+ continue;
412
+ }
413
+ byId.set(u.id, {
414
+ ...existing,
415
+ status: u.status,
416
+ ...u.file !== void 0 ? { file: u.file } : {},
417
+ ...u.details !== void 0 ? { details: u.details } : {}
418
+ });
419
+ }
420
+ return {
421
+ next: current.map((c) => byId.get(c.id) ?? c),
422
+ unknown
423
+ };
424
+ }
425
+ /**
426
+ * Append new checks to a seeded ledger. Duplicate ids are reported without
427
+ * mutating the current ledger, including duplicates inside the additions.
428
+ */
429
+ function applyAuditAdditions(current, additions) {
430
+ const existingIds = new Set(current.map((c) => c.id));
431
+ const additionIds = /* @__PURE__ */ new Set();
432
+ const duplicates = [];
433
+ for (const check of additions) {
434
+ if (existingIds.has(check.id) || additionIds.has(check.id)) {
435
+ duplicates.push(check.id);
436
+ continue;
437
+ }
438
+ additionIds.add(check.id);
439
+ }
440
+ if (duplicates.length > 0) return {
441
+ next: current,
442
+ duplicates
443
+ };
444
+ return {
445
+ next: [...current, ...additions],
446
+ duplicates: []
447
+ };
448
+ }
449
+ function readLedger(targetPath) {
450
+ if (!fs.existsSync(targetPath)) return [];
451
+ try {
452
+ return coerceAuditChecks(JSON.parse(fs.readFileSync(targetPath, "utf8")));
453
+ } catch {
454
+ return [];
455
+ }
456
+ }
457
+ function appendAuditChecksToLedger(targetPath, additions) {
458
+ if (!fs.existsSync(targetPath)) return {
459
+ ok: false,
460
+ reason: "missing-ledger"
461
+ };
462
+ const { next, duplicates } = applyAuditAdditions(readLedger(targetPath), additions);
463
+ if (duplicates.length > 0) return {
464
+ ok: false,
465
+ reason: "duplicate-ids",
466
+ ids: duplicates
467
+ };
468
+ writeLedgerAtomic(targetPath, next);
469
+ return {
470
+ ok: true,
471
+ added: additions.length
472
+ };
473
+ }
474
+ /**
475
+ * Single async mutex shared by audit tools — guarantees a read-modify-write
476
+ * cycle on the ledger is atomic across concurrent tool calls (e.g. future subagents).
477
+ */
478
+ function makeMutex() {
479
+ let chain = Promise.resolve();
480
+ return async function run(fn) {
481
+ const next = chain.then(() => fn());
482
+ chain = next.catch(() => void 0);
483
+ return next;
484
+ };
485
+ }
323
486
  const SERVER_NAME = "wizard-tools";
324
487
  /**
325
488
  * Create the unified in-process MCP server with all wizard tools.
@@ -334,101 +497,162 @@ async function createWizardToolsServer(options) {
334
497
  if (menu) cachedSkillMenu = menu.categories;
335
498
  const keys = Object.keys(cachedSkillMenu);
336
499
  if (keys.length > 0) categoryNames = keys;
500
+ const checkEnvKeys = tool("check_env_keys", "Check which environment variable keys are present or missing in a .env file. Never reveals values.", {
501
+ filePath: z.string().describe("Path to the .env file, relative to the project root"),
502
+ keys: z.array(z.string()).describe("Environment variable key names to check")
503
+ }, (args) => {
504
+ const resolved = resolveEnvPath(workingDirectory, args.filePath);
505
+ logToFile(`check_env_keys: ${resolved}, keys: ${args.keys.join(", ")}`);
506
+ const existingKeys = fs.existsSync(resolved) ? parseEnvKeys(fs.readFileSync(resolved, "utf8")) : /* @__PURE__ */ new Set();
507
+ const results = {};
508
+ for (const key of args.keys) results[key] = existingKeys.has(key) ? "present" : "missing";
509
+ return { content: [{
510
+ type: "text",
511
+ text: JSON.stringify(results, null, 2)
512
+ }] };
513
+ });
514
+ const setEnvValues = tool("set_env_values", "Create or update environment variable keys in a .env file. Creates the file if it does not exist. Ensures .gitignore coverage.", {
515
+ filePath: z.string().describe("Path to the .env file, relative to the project root"),
516
+ values: z.record(z.string(), z.string()).describe("Key-value pairs to set")
517
+ }, (args) => {
518
+ const forbidden = Object.keys(args.values).find((k) => k.toUpperCase() === "POSTHOG_KEY");
519
+ if (forbidden) return {
520
+ content: [{
521
+ type: "text",
522
+ text: `Error: "${forbidden}" is not a valid PostHog env var name. Use the project-specific key name from your framework's integration guide (e.g. NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN).`
523
+ }],
524
+ isError: true
525
+ };
526
+ const resolved = resolveEnvPath(workingDirectory, args.filePath);
527
+ logToFile(`set_env_values: ${resolved}, keys: ${Object.keys(args.values).join(", ")}`);
528
+ const content = mergeEnvValues(fs.existsSync(resolved) ? fs.readFileSync(resolved, "utf8") : "", args.values);
529
+ const dir = path.dirname(resolved);
530
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
531
+ fs.writeFileSync(resolved, content, "utf8");
532
+ ensureGitignoreCoverage(workingDirectory, path.basename(resolved));
533
+ return { content: [{
534
+ type: "text",
535
+ text: `Updated ${Object.keys(args.values).length} key(s) in ${args.filePath}`
536
+ }] };
537
+ });
538
+ const detectPM = tool("detect_package_manager", "Detect which package manager(s) the project uses. Returns the name, install command, and run command for each detected package manager. Call this before running any install commands.", {}, async () => {
539
+ logToFile(`detect_package_manager: scanning ${workingDirectory}`);
540
+ const result = await detectPackageManager(workingDirectory);
541
+ logToFile(`detect_package_manager: detected ${result.detected.length} package manager(s)`);
542
+ return { content: [{
543
+ type: "text",
544
+ text: JSON.stringify(result, null, 2)
545
+ }] };
546
+ });
547
+ const loadSkillMenu = tool("load_skill_menu", "Load available PostHog skills for a category. Returns skill IDs and names. Call this first, then use install_skill with the chosen ID.", { category: z.enum(categoryNames).describe("Skill category") }, (args) => {
548
+ const skills = cachedSkillMenu[args.category];
549
+ if (!skills || skills.length === 0) return {
550
+ content: [{
551
+ type: "text",
552
+ text: `No skills found for category "${args.category}".`
553
+ }],
554
+ isError: true
555
+ };
556
+ const menuText = skills.map((s) => `- ${s.id}: ${s.name}`).join("\n");
557
+ logToFile(`load_skill_menu: returning ${skills.length} skills for "${args.category}"`);
558
+ return { content: [{
559
+ type: "text",
560
+ text: menuText
561
+ }] };
562
+ });
563
+ const installSkill = tool("install_skill", "Download and install a PostHog skill by ID. Call load_skill_menu first to see available skills. Extracts the skill to .claude/skills/<skillId>/.", { skillId: z.string().describe("Skill ID from the skill menu (e.g., \"integration-nextjs-app-router\")") }, (args) => {
564
+ if (!/^[a-z0-9][a-z0-9_-]*$/.test(args.skillId)) return {
565
+ content: [{
566
+ type: "text",
567
+ text: "Error: skillId must be lowercase alphanumeric with hyphens."
568
+ }],
569
+ isError: true
570
+ };
571
+ const skill = Object.values(cachedSkillMenu).flat().find((s) => s.id === args.skillId);
572
+ if (!skill) return {
573
+ content: [{
574
+ type: "text",
575
+ text: `Error: skill "${args.skillId}" not found. Use load_skill_menu to see available skills.`
576
+ }],
577
+ isError: true
578
+ };
579
+ const result = downloadSkill(skill, workingDirectory);
580
+ if (result.success) return { content: [{
581
+ type: "text",
582
+ text: `Skill installed to .claude/skills/${args.skillId}/`
583
+ }] };
584
+ else return {
585
+ content: [{
586
+ type: "text",
587
+ text: `Error installing skill: ${result.error}`
588
+ }],
589
+ isError: true
590
+ };
591
+ });
592
+ const auditLedgerPath = path.join(workingDirectory, AUDIT_CHECKS_FILE);
593
+ const auditMutex = makeMutex();
337
594
  return createSdkMcpServer({
338
595
  name: SERVER_NAME,
339
596
  version: "1.0.0",
340
597
  tools: [
341
- tool("check_env_keys", "Check which environment variable keys are present or missing in a .env file. Never reveals values.", {
342
- filePath: z.string().describe("Path to the .env file, relative to the project root"),
343
- keys: z.array(z.string()).describe("Environment variable key names to check")
344
- }, (args) => {
345
- const resolved = resolveEnvPath(workingDirectory, args.filePath);
346
- logToFile(`check_env_keys: ${resolved}, keys: ${args.keys.join(", ")}`);
347
- const existingKeys = fs.existsSync(resolved) ? parseEnvKeys(fs.readFileSync(resolved, "utf8")) : /* @__PURE__ */ new Set();
348
- const results = {};
349
- for (const key of args.keys) results[key] = existingKeys.has(key) ? "present" : "missing";
350
- return { content: [{
351
- type: "text",
352
- text: JSON.stringify(results, null, 2)
353
- }] };
354
- }),
355
- tool("set_env_values", "Create or update environment variable keys in a .env file. Creates the file if it does not exist. Ensures .gitignore coverage.", {
356
- filePath: z.string().describe("Path to the .env file, relative to the project root"),
357
- values: z.record(z.string(), z.string()).describe("Key-value pairs to set")
358
- }, (args) => {
359
- const forbidden = Object.keys(args.values).find((k) => k.toUpperCase() === "POSTHOG_KEY");
360
- if (forbidden) return {
361
- content: [{
598
+ checkEnvKeys,
599
+ setEnvValues,
600
+ detectPM,
601
+ loadSkillMenu,
602
+ installSkill,
603
+ tool("audit_seed_checks", "Seed the audit ledger at .posthog-audit-checks.json with the full set of pending checks. Call this once at the start of the audit. Atomically replaces any existing ledger.", { checks: z.array(auditCheckSchema).describe("Full pending checklist to write to the ledger") }, async (args) => {
604
+ return auditMutex(() => {
605
+ writeLedgerAtomic(auditLedgerPath, args.checks);
606
+ logToFile(`audit_seed_checks: wrote ${args.checks.length} entries`);
607
+ return { content: [{
362
608
  type: "text",
363
- text: `Error: "${forbidden}" is not a valid PostHog env var name. Use the project-specific key name from your framework's integration guide (e.g. NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN).`
364
- }],
365
- isError: true
366
- };
367
- const resolved = resolveEnvPath(workingDirectory, args.filePath);
368
- logToFile(`set_env_values: ${resolved}, keys: ${Object.keys(args.values).join(", ")}`);
369
- const content = mergeEnvValues(fs.existsSync(resolved) ? fs.readFileSync(resolved, "utf8") : "", args.values);
370
- const dir = path.dirname(resolved);
371
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
372
- fs.writeFileSync(resolved, content, "utf8");
373
- ensureGitignoreCoverage(workingDirectory, path.basename(resolved));
374
- return { content: [{
375
- type: "text",
376
- text: `Updated ${Object.keys(args.values).length} key(s) in ${args.filePath}`
377
- }] };
378
- }),
379
- tool("detect_package_manager", "Detect which package manager(s) the project uses. Returns the name, install command, and run command for each detected package manager. Call this before running any install commands.", {}, async () => {
380
- logToFile(`detect_package_manager: scanning ${workingDirectory}`);
381
- const result = await detectPackageManager(workingDirectory);
382
- logToFile(`detect_package_manager: detected ${result.detected.length} package manager(s)`);
383
- return { content: [{
384
- type: "text",
385
- text: JSON.stringify(result, null, 2)
386
- }] };
609
+ text: `Seeded ${args.checks.length} audit checks.`
610
+ }] };
611
+ });
387
612
  }),
388
- tool("load_skill_menu", "Load available PostHog skills for a category. Returns skill IDs and names. Call this first, then use install_skill with the chosen ID.", { category: z.enum(categoryNames).describe("Skill category") }, (args) => {
389
- const skills = cachedSkillMenu[args.category];
390
- if (!skills || skills.length === 0) return {
391
- content: [{
613
+ tool("audit_add_checks", "Append one or more pending checks to the existing audit ledger at .posthog-audit-checks.json. Call audit_seed_checks first. Atomically rejects duplicate ids without changing the ledger.", { checks: z.array(auditCheckSchema).min(1).describe("Additional checks to append to the existing ledger") }, async (args) => {
614
+ return auditMutex(() => {
615
+ const result = appendAuditChecksToLedger(auditLedgerPath, args.checks);
616
+ if (!result.ok) {
617
+ if (result.reason === "missing-ledger") return {
618
+ content: [{
619
+ type: "text",
620
+ text: "Error: audit ledger does not exist. Run audit_seed_checks first."
621
+ }],
622
+ isError: true
623
+ };
624
+ return {
625
+ content: [{
626
+ type: "text",
627
+ text: `Error: duplicate check id(s): ${result.ids.join(", ")}. Check ids must be unique.`
628
+ }],
629
+ isError: true
630
+ };
631
+ }
632
+ logToFile(`audit_add_checks: added ${result.added} entries`);
633
+ return { content: [{
392
634
  type: "text",
393
- text: `No skills found for category "${args.category}".`
394
- }],
395
- isError: true
396
- };
397
- const menuText = skills.map((s) => `- ${s.id}: ${s.name}`).join("\n");
398
- logToFile(`load_skill_menu: returning ${skills.length} skills for "${args.category}"`);
399
- return { content: [{
400
- type: "text",
401
- text: menuText
402
- }] };
635
+ text: `Added ${result.added} audit check(s).`
636
+ }] };
637
+ });
403
638
  }),
404
- tool("install_skill", "Download and install a PostHog skill by ID. Call load_skill_menu first to see available skills. Extracts the skill to .claude/skills/<skillId>/.", { skillId: z.string().describe("Skill ID from the skill menu (e.g., \"integration-nextjs-app-router\")") }, (args) => {
405
- if (!/^[a-z0-9][a-z0-9_-]*$/.test(args.skillId)) return {
406
- content: [{
639
+ tool("audit_resolve_checks", "Resolve one or more audit checks by id. Patches each entry's status (and optional file/details) and writes the ledger back atomically. Concurrent calls serialize.", { updates: z.array(auditUpdateSchema).min(1).describe("Patches to apply, keyed by check id") }, async (args) => {
640
+ return auditMutex(() => {
641
+ const { next, unknown } = applyAuditUpdates(readLedger(auditLedgerPath), args.updates);
642
+ if (unknown.length > 0) return {
643
+ content: [{
644
+ type: "text",
645
+ text: `Error: unknown check id(s): ${unknown.join(", ")}. Run audit_seed_checks first or check the id.`
646
+ }],
647
+ isError: true
648
+ };
649
+ writeLedgerAtomic(auditLedgerPath, next);
650
+ logToFile(`audit_resolve_checks: applied ${args.updates.length} update(s)`);
651
+ return { content: [{
407
652
  type: "text",
408
- text: "Error: skillId must be lowercase alphanumeric with hyphens."
409
- }],
410
- isError: true
411
- };
412
- const skill = Object.values(cachedSkillMenu).flat().find((s) => s.id === args.skillId);
413
- if (!skill) return {
414
- content: [{
415
- type: "text",
416
- text: `Error: skill "${args.skillId}" not found. Use load_skill_menu to see available skills.`
417
- }],
418
- isError: true
419
- };
420
- const result = downloadSkill(skill, workingDirectory);
421
- if (result.success) return { content: [{
422
- type: "text",
423
- text: `Skill installed to .claude/skills/${args.skillId}/`
424
- }] };
425
- else return {
426
- content: [{
427
- type: "text",
428
- text: `Error installing skill: ${result.error}`
429
- }],
430
- isError: true
431
- };
653
+ text: `Resolved ${args.updates.length} check(s).`
654
+ }] };
655
+ });
432
656
  })
433
657
  ]
434
658
  });
@@ -439,7 +663,10 @@ const WIZARD_TOOL_NAMES = [
439
663
  `${SERVER_NAME}:set_env_values`,
440
664
  `${SERVER_NAME}:detect_package_manager`,
441
665
  `${SERVER_NAME}:load_skill_menu`,
442
- `${SERVER_NAME}:install_skill`
666
+ `${SERVER_NAME}:install_skill`,
667
+ `${SERVER_NAME}:audit_seed_checks`,
668
+ `${SERVER_NAME}:audit_add_checks`,
669
+ `${SERVER_NAME}:audit_resolve_checks`
443
670
  ];
444
671
  //#endregion
445
672
  //#region src/lib/yara-scanner.ts
@@ -749,7 +976,6 @@ function formatScanReport() {
749
976
  lines.push("");
750
977
  return lines.join("\n");
751
978
  }
752
- const YARA_REPORT_PATH = "/tmp/posthog-wizard-yara-report.json";
753
979
  /** Write the scan report to a JSON file. Returns the file path, or null if no scans occurred. */
754
980
  function writeScanReport() {
755
981
  if (scanCount === 0) return null;
@@ -762,12 +988,12 @@ function writeScanReport() {
762
988
  violations: scanViolations
763
989
  };
764
990
  try {
765
- fs.writeFileSync(YARA_REPORT_PATH, JSON.stringify(report, null, 2));
991
+ fs.writeFileSync(WIZARD_YARA_REPORT_FILE, JSON.stringify(report, null, 2));
766
992
  } catch (err) {
767
993
  logToFile("[YARA] Failed to write scan report:", err);
768
994
  return null;
769
995
  }
770
- return YARA_REPORT_PATH;
996
+ return WIZARD_YARA_REPORT_FILE;
771
997
  }
772
998
  /** Timeout for synchronous scan hooks (PreToolUse, PostToolUse Write/Edit/Read) */
773
999
  const HOOK_TIMEOUT_MS = 60;
@@ -1187,10 +1413,13 @@ function buildWizardMetadata(flags = {}) {
1187
1413
  return { ...(variantKey && WIZARD_VARIANTS[variantKey]) ?? WIZARD_VARIANTS["base"] };
1188
1414
  }
1189
1415
  /**
1190
- * Build env for the SDK subprocess: process.env plus ANTHROPIC_CUSTOM_HEADERS from wizard metadata/flags.
1416
+ * Build env for the SDK subprocess: process.env plus ANTHROPIC_CUSTOM_HEADERS, which always
1417
+ * includes `x-posthog-use-bedrock-fallback: true` so the LLM gateway falls back to Bedrock on
1418
+ * Anthropic 5xx, plus any wizard metadata/flags.
1191
1419
  */
1192
1420
  function buildAgentEnv(wizardMetadata, wizardFlags) {
1193
1421
  const headers = createCustomHeaders();
1422
+ headers.add("x-posthog-use-bedrock-fallback", "true");
1194
1423
  for (const [key, value] of Object.entries(wizardMetadata)) headers.add(key.startsWith("X-POSTHOG-PROPERTY-") ? key : `${POSTHOG_PROPERTY_HEADER_PREFIX}${key}`, value);
1195
1424
  for (const [flagKey, variant] of Object.entries(wizardFlags)) {
1196
1425
  if (!flagKey.toLowerCase().startsWith("wizard")) continue;
@@ -1496,8 +1725,6 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
1496
1725
  spinner.stop(successMessage);
1497
1726
  return {};
1498
1727
  };
1499
- let eventPlanWatcher;
1500
- let eventPlanInterval;
1501
1728
  const abortController = new AbortController();
1502
1729
  let abortReason = null;
1503
1730
  try {
@@ -1508,6 +1735,7 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
1508
1735
  "Glob",
1509
1736
  "Grep",
1510
1737
  "Bash",
1738
+ "Task",
1511
1739
  "ListMcpResourcesTool",
1512
1740
  "Skill",
1513
1741
  ...WIZARD_TOOL_NAMES
@@ -1586,31 +1814,6 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
1586
1814
  }
1587
1815
  }
1588
1816
  });
1589
- const eventPlanPath = path.join(agentConfig.workingDirectory, ".posthog-events.json");
1590
- const readEventPlan = () => {
1591
- try {
1592
- const content = fs$1.readFileSync(eventPlanPath, "utf-8");
1593
- const parsed = JSON.parse(content);
1594
- if (Array.isArray(parsed)) getUI().setEventPlan(parsed.map((e) => ({
1595
- name: e.name ?? e.event ?? "",
1596
- description: e.description ?? ""
1597
- })));
1598
- } catch {}
1599
- };
1600
- try {
1601
- eventPlanWatcher = fs$1.watch(eventPlanPath, () => readEventPlan());
1602
- readEventPlan();
1603
- } catch {
1604
- eventPlanInterval = setInterval(() => {
1605
- try {
1606
- fs$1.accessSync(eventPlanPath);
1607
- readEventPlan();
1608
- clearInterval(eventPlanInterval);
1609
- eventPlanInterval = void 0;
1610
- eventPlanWatcher = fs$1.watch(eventPlanPath, () => readEventPlan());
1611
- } catch {}
1612
- }, 1e3);
1613
- }
1614
1817
  for await (const message of response) {
1615
1818
  if (!loggedInitialContext && message.type === "assistant") {
1616
1819
  const usage = message.message?.usage;
@@ -1744,8 +1947,6 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
1744
1947
  debug("Full error:", error);
1745
1948
  throw error;
1746
1949
  } finally {
1747
- eventPlanWatcher?.close();
1748
- if (eventPlanInterval) clearInterval(eventPlanInterval);
1749
1950
  if (!receivedSuccessResult) {
1750
1951
  const durationMs = Date.now() - startTime;
1751
1952
  analytics.wizardCapture("agent aborted", {
@@ -1815,342 +2016,6 @@ function handleSDKMessage(message, options, spinner, collectedText, receivedSucc
1815
2016
  }
1816
2017
  }
1817
2018
  //#endregion
1818
- //#region src/lib/health-checks/statuspage.ts
1819
- function mapIndicator(v) {
1820
- switch (v) {
1821
- case "none": return "healthy";
1822
- case "minor": return "degraded";
1823
- case "major":
1824
- case "critical": return "down";
1825
- default: return "degraded";
1826
- }
1827
- }
1828
- function mapComponentRaw(v) {
1829
- switch (v) {
1830
- case "operational": return "healthy";
1831
- case "degraded_performance":
1832
- case "under_maintenance": return "degraded";
1833
- case "partial_outage":
1834
- case "major_outage": return "down";
1835
- default: return "degraded";
1836
- }
1837
- }
1838
- function errResult$1(error) {
1839
- return {
1840
- status: "degraded",
1841
- error
1842
- };
1843
- }
1844
- async function fetchStatuspageIndicator(url, timeoutMs = 5e3) {
1845
- try {
1846
- const controller = new AbortController();
1847
- const tid = setTimeout(() => controller.abort(), timeoutMs);
1848
- const res = await fetch(url, { signal: controller.signal });
1849
- clearTimeout(tid);
1850
- if (!res.ok) return errResult$1(`HTTP ${res.status}`);
1851
- const indicator = (await res.json()).status?.indicator ?? null;
1852
- return {
1853
- status: mapIndicator(indicator),
1854
- rawIndicator: indicator ?? void 0
1855
- };
1856
- } catch (e) {
1857
- if (e instanceof Error && e.name === "AbortError") return errResult$1("Request timed out");
1858
- return errResult$1(e instanceof Error ? e.message : "Unknown error");
1859
- }
1860
- }
1861
- async function fetchStatuspageSummary(url, timeoutMs = 5e3) {
1862
- try {
1863
- const controller = new AbortController();
1864
- const tid = setTimeout(() => controller.abort(), timeoutMs);
1865
- const res = await fetch(url, { signal: controller.signal });
1866
- clearTimeout(tid);
1867
- if (!res.ok) return errResult$1(`HTTP ${res.status}`);
1868
- const data = await res.json();
1869
- const indicator = data.status?.indicator ?? null;
1870
- const overall = mapIndicator(indicator);
1871
- const affected = (data.components ?? []).map((c) => ({
1872
- name: c.name,
1873
- status: mapComponentRaw(c.status),
1874
- rawStatus: c.status
1875
- })).filter((c) => c.status !== "healthy");
1876
- return {
1877
- status: affected.length > 0 ? "degraded" : overall,
1878
- rawIndicator: indicator ?? void 0,
1879
- degradedOrDownComponents: affected.length > 0 ? affected : void 0
1880
- };
1881
- } catch (e) {
1882
- if (e instanceof Error && e.name === "AbortError") return errResult$1("Request timed out");
1883
- return errResult$1(e instanceof Error ? e.message : "Unknown error");
1884
- }
1885
- }
1886
- const checkAnthropicHealth = () => fetchStatuspageIndicator("https://status.claude.com/api/v2/status.json");
1887
- const checkGithubHealth = () => fetchStatuspageIndicator("https://www.githubstatus.com/api/v2/status.json");
1888
- const checkNpmOverallHealth = () => fetchStatuspageIndicator("https://status.npmjs.org/api/v2/status.json");
1889
- const checkNpmComponentHealth = () => fetchStatuspageSummary("https://status.npmjs.org/api/v2/summary.json");
1890
- const checkCloudflareOverallHealth = () => fetchStatuspageIndicator("https://www.cloudflarestatus.com/api/v2/status.json");
1891
- const checkCloudflareComponentHealth = () => fetchStatuspageSummary("https://www.cloudflarestatus.com/api/v2/summary.json");
1892
- //#endregion
1893
- //#region src/lib/health-checks/incidentio.ts
1894
- function mapIncidentImpact(impact) {
1895
- switch (impact) {
1896
- case "full_outage": return "down";
1897
- case "partial_outage":
1898
- case "degraded_performance": return "degraded";
1899
- default: return "degraded";
1900
- }
1901
- }
1902
- function mapComponentStatus(status) {
1903
- switch (status) {
1904
- case "operational": return "healthy";
1905
- case "full_outage": return "down";
1906
- case "partial_outage":
1907
- case "degraded_performance": return "degraded";
1908
- default: return "degraded";
1909
- }
1910
- }
1911
- function errResult(error) {
1912
- return {
1913
- status: "degraded",
1914
- error
1915
- };
1916
- }
1917
- const POSTHOG_STATUS_URL = "https://www.posthogstatus.com/api/v1/summary";
1918
- async function fetchPosthogStatus(timeoutMs = 5e3) {
1919
- try {
1920
- const controller = new AbortController();
1921
- const tid = setTimeout(() => controller.abort(), timeoutMs);
1922
- const res = await fetch(POSTHOG_STATUS_URL, { signal: controller.signal });
1923
- clearTimeout(tid);
1924
- if (!res.ok) {
1925
- const err = errResult(`HTTP ${res.status}`);
1926
- return {
1927
- overall: err,
1928
- components: err
1929
- };
1930
- }
1931
- const incidents = (await res.json()).ongoing_incidents ?? [];
1932
- if (incidents.length === 0) return {
1933
- overall: { status: "healthy" },
1934
- components: { status: "healthy" }
1935
- };
1936
- let worstOverall = "degraded";
1937
- const affected = [];
1938
- for (const incident of incidents) {
1939
- if (mapIncidentImpact(incident.current_worst_impact) === "down") worstOverall = "down";
1940
- for (const comp of incident.affected_components ?? []) {
1941
- const compStatus = mapComponentStatus(comp.current_status);
1942
- if (compStatus !== "healthy") affected.push({
1943
- name: comp.group_name ? `${comp.group_name} — ${comp.name}` : comp.name,
1944
- status: compStatus,
1945
- rawStatus: comp.current_status
1946
- });
1947
- }
1948
- }
1949
- return {
1950
- overall: { status: worstOverall },
1951
- components: {
1952
- status: affected.length > 0 ? "degraded" : worstOverall,
1953
- degradedOrDownComponents: affected.length > 0 ? affected : void 0
1954
- }
1955
- };
1956
- } catch (e) {
1957
- if (e instanceof Error && e.name === "AbortError") {
1958
- const err = errResult("Request timed out");
1959
- return {
1960
- overall: err,
1961
- components: err
1962
- };
1963
- }
1964
- const err = errResult(e instanceof Error ? e.message : "Unknown error");
1965
- return {
1966
- overall: err,
1967
- components: err
1968
- };
1969
- }
1970
- }
1971
- let _cache = null;
1972
- function getPosthogHealth() {
1973
- if (!_cache) _cache = fetchPosthogStatus();
1974
- return _cache;
1975
- }
1976
- const checkPosthogOverallHealth = async () => (await getPosthogHealth()).overall;
1977
- const checkPosthogComponentHealth = async () => (await getPosthogHealth()).components;
1978
- //#endregion
1979
- //#region src/lib/health-checks/endpoints.ts
1980
- function downResult(error) {
1981
- return {
1982
- status: "down",
1983
- error
1984
- };
1985
- }
1986
- async function fetchEndpointHealth(url, timeoutMs = 5e3, expectedStatus = 200) {
1987
- try {
1988
- const controller = new AbortController();
1989
- const tid = setTimeout(() => controller.abort(), timeoutMs);
1990
- const res = await fetch(url, { signal: controller.signal });
1991
- clearTimeout(tid);
1992
- if (res.status === expectedStatus) return {
1993
- status: "healthy",
1994
- rawIndicator: `HTTP ${res.status}`
1995
- };
1996
- return downResult(`HTTP ${res.status}`);
1997
- } catch (e) {
1998
- if (e instanceof Error && e.name === "AbortError") return downResult("Request timed out");
1999
- return downResult(e instanceof Error ? e.message : "Unknown error");
2000
- }
2001
- }
2002
- const checkLlmGatewayHealth = () => fetchEndpointHealth("https://gateway.us.posthog.com/_liveness");
2003
- const checkMcpHealth = () => fetchEndpointHealth("https://mcp.posthog.com/");
2004
- const checkGithubReleasesHealth = () => fetchEndpointHealth(`${REMOTE_SKILLS_BASE_URL}/skill-menu.json`);
2005
- //#endregion
2006
- //#region src/lib/health-checks/readiness.ts
2007
- const SERVICE_LABELS = {
2008
- anthropic: "Anthropic",
2009
- posthogOverall: "PostHog",
2010
- posthogComponents: "PostHog (components)",
2011
- github: "GitHub",
2012
- npmOverall: "npm",
2013
- npmComponents: "npm (components)",
2014
- cloudflareOverall: "Cloudflare",
2015
- cloudflareComponents: "Cloudflare (components)",
2016
- llmGateway: "LLM Gateway",
2017
- mcp: "MCP",
2018
- githubReleases: "GitHub Releases"
2019
- };
2020
- /**
2021
- * See README section "Health checks" for the full rationale.
2022
- * Adjust these arrays to change what blocks a wizard run.
2023
- */
2024
- const DEFAULT_WIZARD_READINESS_CONFIG = {
2025
- downBlocksRun: [
2026
- "anthropic",
2027
- "npmOverall",
2028
- "llmGateway",
2029
- "mcp",
2030
- "githubReleases"
2031
- ],
2032
- degradedBlocksRun: ["anthropic"]
2033
- };
2034
- async function checkAllExternalServices() {
2035
- const [anthropic, posthogOverall, posthogComponents, github, npmOverall, npmComponents, cloudflareOverall, cloudflareComponents, llmGateway, mcp, githubReleases] = await Promise.all([
2036
- checkAnthropicHealth(),
2037
- checkPosthogOverallHealth(),
2038
- checkPosthogComponentHealth(),
2039
- checkGithubHealth(),
2040
- checkNpmOverallHealth(),
2041
- checkNpmComponentHealth(),
2042
- checkCloudflareOverallHealth(),
2043
- checkCloudflareComponentHealth(),
2044
- checkLlmGatewayHealth(),
2045
- checkMcpHealth(),
2046
- checkGithubReleasesHealth()
2047
- ]);
2048
- return {
2049
- anthropic,
2050
- posthogOverall,
2051
- posthogComponents,
2052
- github,
2053
- npmOverall,
2054
- npmComponents,
2055
- cloudflareOverall,
2056
- cloudflareComponents,
2057
- llmGateway,
2058
- mcp,
2059
- githubReleases
2060
- };
2061
- }
2062
- function describeResult(label, h) {
2063
- const parts = [`${label}: ${h.status}`];
2064
- if (h.rawIndicator) parts.push(`indicator=${h.rawIndicator}`);
2065
- if (h.error) parts.push(h.error);
2066
- return parts.join(" — ");
2067
- }
2068
- const MAX_COMPONENT_NAMES = 8;
2069
- function describeComponents(label, h) {
2070
- const affected = h.degradedOrDownComponents;
2071
- if (!affected || affected.length === 0) return `${label} components: all operational`;
2072
- const shown = affected.slice(0, MAX_COMPONENT_NAMES).map((c) => `${c.name} (${c.status})`);
2073
- const suffix = affected.length > MAX_COMPONENT_NAMES ? `, +${affected.length - MAX_COMPONENT_NAMES} more` : "";
2074
- return `${label} components impacted: ${shown.join(", ")}${suffix}`;
2075
- }
2076
- const READINESS_TIMEOUT_MS = 1e4;
2077
- async function evaluateWizardReadiness(config = DEFAULT_WIZARD_READINESS_CONFIG) {
2078
- try {
2079
- const health = await Promise.race([checkAllExternalServices(), new Promise((resolve) => setTimeout(() => resolve(allUnknown("Health check timed out")), READINESS_TIMEOUT_MS))]);
2080
- const reasons = [];
2081
- for (const key of Object.keys(health)) {
2082
- const result = health[key];
2083
- const label = SERVICE_LABELS[key];
2084
- reasons.push(describeResult(label, result));
2085
- if ("degradedOrDownComponents" in result) reasons.push(describeComponents(label, result));
2086
- }
2087
- const blockingKeys = getBlockingServiceKeys(health, config);
2088
- if (blockingKeys.length > 0) {
2089
- logToFile(`[health-checks] blocked by: ${blockingKeys.join(", ")}`);
2090
- return {
2091
- decision: "no",
2092
- health,
2093
- reasons
2094
- };
2095
- }
2096
- if (Object.values(health).some((h) => h.status !== "healthy")) return {
2097
- decision: "yes_with_warnings",
2098
- health,
2099
- reasons
2100
- };
2101
- return {
2102
- decision: "yes",
2103
- health,
2104
- reasons
2105
- };
2106
- } catch (err) {
2107
- logToFile(`[health-checks] error: ${err instanceof Error ? err.message : err}`);
2108
- return {
2109
- decision: "yes",
2110
- health: allUnknown("Unexpected error"),
2111
- reasons: ["Health check failed unexpectedly — proceeding anyway"]
2112
- };
2113
- }
2114
- }
2115
- /** Keys that are component-level detail, not top-level services. */
2116
- const COMPONENT_KEYS = [
2117
- "posthogComponents",
2118
- "npmComponents",
2119
- "cloudflareComponents"
2120
- ];
2121
- /**
2122
- * Get the keys of services that would block a wizard run per the given config.
2123
- */
2124
- function getBlockingServiceKeys(health, config = DEFAULT_WIZARD_READINESS_CONFIG) {
2125
- return Object.keys(health).filter((key) => {
2126
- if (COMPONENT_KEYS.includes(key)) return false;
2127
- const result = health[key];
2128
- if (config.downBlocksRun.includes(key) && result.status === "down") return true;
2129
- if ((config.degradedBlocksRun ?? []).includes(key) && result.status !== "healthy") return true;
2130
- return false;
2131
- });
2132
- }
2133
- /** Build an AllServicesHealth where every service is Degraded with the given error. */
2134
- function allUnknown(error) {
2135
- const base = {
2136
- status: "degraded",
2137
- error
2138
- };
2139
- return {
2140
- anthropic: base,
2141
- posthogOverall: base,
2142
- posthogComponents: { ...base },
2143
- github: base,
2144
- npmOverall: base,
2145
- npmComponents: { ...base },
2146
- cloudflareOverall: base,
2147
- cloudflareComponents: { ...base },
2148
- llmGateway: base,
2149
- mcp: base,
2150
- githubReleases: base
2151
- };
2152
- }
2153
- //#endregion
2154
- export { backupAndFixClaudeSettings as a, initializeAgent as c, formatScanReport as d, writeScanReport as f, installSkillById as h, AgentSignals as i, restoreClaudeSettings as l, fetchSkillMenu as m, evaluateWizardReadiness as n, buildWizardMetadata as o, downloadSkill as p, getBlockingServiceKeys as r, checkAllSettingsConflicts as s, SERVICE_LABELS as t, runAgent as u };
2019
+ export { coerceAuditChecks as _, initializeAgent as a, formatScanReport as c, fetchSkillMenu as d, installSkillById as f, AUDIT_SEVERITY_STYLE as g, AUDIT_REPORT_FILE as h, checkAllSettingsConflicts as i, writeScanReport as l, AUDIT_CHECKS_KEY as m, backupAndFixClaudeSettings as n, restoreClaudeSettings as o, AUDIT_CHECKS_FILE as p, buildWizardMetadata as r, runAgent as s, AgentSignals as t, downloadSkill as u, getAuditChecks as v };
2155
2020
 
2156
- //# sourceMappingURL=readiness-Cep84RsR.js.map
2021
+ //# sourceMappingURL=agent-interface-D5W9BAB2.js.map