@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
@@ -1,10 +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-gWEjmYVV.js";
3
- import { C as WIZARD_USER_AGENT, T as WIZARD_VARIANT_FLAG_KEY, g as POSTHOG_PROPERTY_HEADER_PREFIX, m as POSTHOG_FLAG_HEADER_PREFIX, n as analytics, w as WIZARD_VARIANTS, x as WIZARD_REMARK_EVENT_NAME, y as REMOTE_SKILLS_BASE_URL } from "./analytics-D3rY3TaN.js";
4
- import { a as skillTmpPath, i as WIZARD_YARA_REPORT_FILE } from "./paths-BL-x2rFy.js";
5
- import { f as getLlmGatewayUrlFromHost } from "./setup-utils-y4s-3uKT.js";
6
- import { n as ADDITIONAL_FEATURE_PROMPTS } from "./wizard-session-D5bggSsu.js";
7
- import { n as registerCleanup, r as wizardAbort, t as WizardError } from "./wizard-abort-Buodno3f.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-Cqi6nVfX.js";
3
+ import { i as WIZARD_YARA_REPORT_FILE, o as skillTmpPath } from "./paths-DJS47p5x.js";
4
+ import { n as analytics } from "./analytics-VM7laaFx.js";
5
+ import { f as getLlmGatewayUrlFromHost } from "./setup-utils-CNV7FSlY.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-CJkNkSjT.js";
8
8
  import * as fs$1 from "fs";
9
9
  import fs from "fs";
10
10
  import path from "path";
@@ -175,6 +175,49 @@ const LINTING_TOOLS = [
175
175
  "yamllint"
176
176
  ];
177
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
178
221
  //#region src/lib/wizard-tools.ts
179
222
  /**
180
223
  * Unified in-process MCP server for the PostHog wizard.
@@ -183,6 +226,8 @@ const LINTING_TOOLS = [
183
226
  * - check_env_keys: Check which env var keys exist in a .env file
184
227
  * - set_env_values: Create/update env vars in a .env file
185
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
186
231
  */
187
232
  let _sdkModule$1 = null;
188
233
  async function getSDKModule$1() {
@@ -232,6 +277,7 @@ function downloadSkill(skillEntry, installDir, skillsRoot) {
232
277
  "-d",
233
278
  skillDir
234
279
  ], { timeout: 3e4 });
280
+ fs.writeFileSync(path.join(skillDir, ".posthog-wizard"), "");
235
281
  try {
236
282
  fs.unlinkSync(tmpFile);
237
283
  } catch {}
@@ -321,6 +367,122 @@ function mergeEnvValues(content, values) {
321
367
  }
322
368
  return result;
323
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
+ }
324
486
  const SERVER_NAME = "wizard-tools";
325
487
  /**
326
488
  * Create the unified in-process MCP server with all wizard tools.
@@ -335,101 +497,162 @@ async function createWizardToolsServer(options) {
335
497
  if (menu) cachedSkillMenu = menu.categories;
336
498
  const keys = Object.keys(cachedSkillMenu);
337
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();
338
594
  return createSdkMcpServer({
339
595
  name: SERVER_NAME,
340
596
  version: "1.0.0",
341
597
  tools: [
342
- tool("check_env_keys", "Check which environment variable keys are present or missing in a .env file. Never reveals values.", {
343
- filePath: z.string().describe("Path to the .env file, relative to the project root"),
344
- keys: z.array(z.string()).describe("Environment variable key names to check")
345
- }, (args) => {
346
- const resolved = resolveEnvPath(workingDirectory, args.filePath);
347
- logToFile(`check_env_keys: ${resolved}, keys: ${args.keys.join(", ")}`);
348
- const existingKeys = fs.existsSync(resolved) ? parseEnvKeys(fs.readFileSync(resolved, "utf8")) : /* @__PURE__ */ new Set();
349
- const results = {};
350
- for (const key of args.keys) results[key] = existingKeys.has(key) ? "present" : "missing";
351
- return { content: [{
352
- type: "text",
353
- text: JSON.stringify(results, null, 2)
354
- }] };
355
- }),
356
- 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.", {
357
- filePath: z.string().describe("Path to the .env file, relative to the project root"),
358
- values: z.record(z.string(), z.string()).describe("Key-value pairs to set")
359
- }, (args) => {
360
- const forbidden = Object.keys(args.values).find((k) => k.toUpperCase() === "POSTHOG_KEY");
361
- if (forbidden) return {
362
- 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: [{
363
608
  type: "text",
364
- 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).`
365
- }],
366
- isError: true
367
- };
368
- const resolved = resolveEnvPath(workingDirectory, args.filePath);
369
- logToFile(`set_env_values: ${resolved}, keys: ${Object.keys(args.values).join(", ")}`);
370
- const content = mergeEnvValues(fs.existsSync(resolved) ? fs.readFileSync(resolved, "utf8") : "", args.values);
371
- const dir = path.dirname(resolved);
372
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
373
- fs.writeFileSync(resolved, content, "utf8");
374
- ensureGitignoreCoverage(workingDirectory, path.basename(resolved));
375
- return { content: [{
376
- type: "text",
377
- text: `Updated ${Object.keys(args.values).length} key(s) in ${args.filePath}`
378
- }] };
379
- }),
380
- 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 () => {
381
- logToFile(`detect_package_manager: scanning ${workingDirectory}`);
382
- const result = await detectPackageManager(workingDirectory);
383
- logToFile(`detect_package_manager: detected ${result.detected.length} package manager(s)`);
384
- return { content: [{
385
- type: "text",
386
- text: JSON.stringify(result, null, 2)
387
- }] };
609
+ text: `Seeded ${args.checks.length} audit checks.`
610
+ }] };
611
+ });
388
612
  }),
389
- 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) => {
390
- const skills = cachedSkillMenu[args.category];
391
- if (!skills || skills.length === 0) return {
392
- 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: [{
393
634
  type: "text",
394
- text: `No skills found for category "${args.category}".`
395
- }],
396
- isError: true
397
- };
398
- const menuText = skills.map((s) => `- ${s.id}: ${s.name}`).join("\n");
399
- logToFile(`load_skill_menu: returning ${skills.length} skills for "${args.category}"`);
400
- return { content: [{
401
- type: "text",
402
- text: menuText
403
- }] };
635
+ text: `Added ${result.added} audit check(s).`
636
+ }] };
637
+ });
404
638
  }),
405
- 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) => {
406
- if (!/^[a-z0-9][a-z0-9_-]*$/.test(args.skillId)) return {
407
- 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: [{
408
652
  type: "text",
409
- text: "Error: skillId must be lowercase alphanumeric with hyphens."
410
- }],
411
- isError: true
412
- };
413
- const skill = Object.values(cachedSkillMenu).flat().find((s) => s.id === args.skillId);
414
- if (!skill) return {
415
- content: [{
416
- type: "text",
417
- text: `Error: skill "${args.skillId}" not found. Use load_skill_menu to see available skills.`
418
- }],
419
- isError: true
420
- };
421
- const result = downloadSkill(skill, workingDirectory);
422
- if (result.success) return { content: [{
423
- type: "text",
424
- text: `Skill installed to .claude/skills/${args.skillId}/`
425
- }] };
426
- else return {
427
- content: [{
428
- type: "text",
429
- text: `Error installing skill: ${result.error}`
430
- }],
431
- isError: true
432
- };
653
+ text: `Resolved ${args.updates.length} check(s).`
654
+ }] };
655
+ });
433
656
  })
434
657
  ]
435
658
  });
@@ -440,7 +663,10 @@ const WIZARD_TOOL_NAMES = [
440
663
  `${SERVER_NAME}:set_env_values`,
441
664
  `${SERVER_NAME}:detect_package_manager`,
442
665
  `${SERVER_NAME}:load_skill_menu`,
443
- `${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`
444
670
  ];
445
671
  //#endregion
446
672
  //#region src/lib/yara-scanner.ts
@@ -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;
@@ -1394,10 +1623,11 @@ async function initializeAgent(config, options) {
1394
1623
  detectPackageManager: config.detectPackageManager,
1395
1624
  skillsBaseUrl: config.skillsBaseUrl
1396
1625
  });
1626
+ const model = config.integrationLabel === "audit-3000" ? "anthropic/claude-opus-4-7" : "anthropic/claude-sonnet-4-6";
1397
1627
  const agentRunConfig = {
1398
1628
  workingDirectory: config.workingDirectory,
1399
1629
  mcpServers,
1400
- model: "anthropic/claude-sonnet-4-6",
1630
+ model,
1401
1631
  wizardFlags: config.wizardFlags,
1402
1632
  wizardMetadata: config.wizardMetadata
1403
1633
  };
@@ -1496,8 +1726,6 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
1496
1726
  spinner.stop(successMessage);
1497
1727
  return {};
1498
1728
  };
1499
- let eventPlanWatcher;
1500
- let eventPlanInterval;
1501
1729
  const abortController = new AbortController();
1502
1730
  let abortReason = null;
1503
1731
  try {
@@ -1508,6 +1736,7 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
1508
1736
  "Glob",
1509
1737
  "Grep",
1510
1738
  "Bash",
1739
+ "Task",
1511
1740
  "ListMcpResourcesTool",
1512
1741
  "Skill",
1513
1742
  ...WIZARD_TOOL_NAMES
@@ -1586,31 +1815,6 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
1586
1815
  }
1587
1816
  }
1588
1817
  });
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
1818
  for await (const message of response) {
1615
1819
  if (!loggedInitialContext && message.type === "assistant") {
1616
1820
  const usage = message.message?.usage;
@@ -1744,8 +1948,6 @@ async function runAgent(agentConfig, prompt, options, spinner, config, middlewar
1744
1948
  debug("Full error:", error);
1745
1949
  throw error;
1746
1950
  } finally {
1747
- eventPlanWatcher?.close();
1748
- if (eventPlanInterval) clearInterval(eventPlanInterval);
1749
1951
  if (!receivedSuccessResult) {
1750
1952
  const durationMs = Date.now() - startTime;
1751
1953
  analytics.wizardCapture("agent aborted", {
@@ -1815,342 +2017,6 @@ function handleSDKMessage(message, options, spinner, collectedText, receivedSucc
1815
2017
  }
1816
2018
  }
1817
2019
  //#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 };
2020
+ 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
2021
 
2156
- //# sourceMappingURL=readiness-gQvQNCeL.js.map
2022
+ //# sourceMappingURL=agent-interface-CV0-vtxj.js.map