vybekiit 0.7.0 → 0.7.2

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 (94) hide show
  1. package/dist/bin.js +1697 -562
  2. package/dist/global-skills/add-ai/SKILL.md +1 -1
  3. package/dist/global-skills/add-analytics/SKILL.md +1 -1
  4. package/dist/global-skills/add-blog/SKILL.md +1 -1
  5. package/dist/global-skills/add-crud/SKILL.md +1 -1
  6. package/dist/global-skills/add-files/SKILL.md +1 -1
  7. package/dist/global-skills/add-images/SKILL.md +1 -1
  8. package/dist/global-skills/add-language/SKILL.md +1 -1
  9. package/dist/global-skills/add-notifications/SKILL.md +1 -1
  10. package/dist/global-skills/add-realtime/SKILL.md +1 -1
  11. package/dist/global-skills/add-route/SKILL.md +1 -1
  12. package/dist/global-skills/add-search/SKILL.md +1 -1
  13. package/dist/global-skills/add-signin/SKILL.md +1 -1
  14. package/dist/global-skills/add-teams/SKILL.md +1 -1
  15. package/dist/global-skills/add-upload/SKILL.md +1 -1
  16. package/dist/global-skills/aws-serverless/SKILL.md +44 -44
  17. package/dist/global-skills/aws-serverless/assets/powertools-handler.py +1 -2
  18. package/dist/global-skills/aws-serverless/references/api-gateway.md +470 -50
  19. package/dist/global-skills/aws-serverless/references/architecture.md +186 -47
  20. package/dist/global-skills/aws-serverless/references/concurrency.md +158 -44
  21. package/dist/global-skills/aws-serverless/references/deployment.md +1 -1
  22. package/dist/global-skills/aws-serverless/references/event-sources.md +391 -72
  23. package/dist/global-skills/aws-serverless/references/lambda.md +428 -69
  24. package/dist/global-skills/aws-serverless/references/orchestration.md +384 -65
  25. package/dist/global-skills/aws-serverless/references/production.md +415 -78
  26. package/dist/global-skills/aws-serverless/references/troubleshooting.md +626 -79
  27. package/dist/global-skills/back-up-my-code/SKILL.md +1 -1
  28. package/dist/global-skills/buy-domain/SKILL.md +1 -1
  29. package/dist/global-skills/check-safety/SKILL.md +1 -1
  30. package/dist/global-skills/configure-capabilities/SKILL.md +1 -1
  31. package/dist/global-skills/connect-account/SKILL.md +1 -1
  32. package/dist/global-skills/connect-account-backend/SKILL.md +1 -1
  33. package/dist/global-skills/design-my-data/SKILL.md +1 -1
  34. package/dist/global-skills/doctor/SKILL.md +1 -1
  35. package/dist/global-skills/feedback/SKILL.md +63 -0
  36. package/dist/global-skills/go-live/SKILL.md +1 -1
  37. package/dist/global-skills/harden/SKILL.md +1 -1
  38. package/dist/global-skills/instrument-feature-flags/references/usage.md +0 -35
  39. package/dist/global-skills/instrument-product-analytics/SKILL.md +1 -1
  40. package/dist/global-skills/instrument-product-analytics/references/android.md +0 -36
  41. package/dist/global-skills/instrument-product-analytics/references/configuration.md +0 -1
  42. package/dist/global-skills/instrument-product-analytics/references/flutter.md +0 -37
  43. package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +2 -3
  44. package/dist/global-skills/instrument-product-analytics/references/usage.md +0 -35
  45. package/dist/global-skills/manifest.json +2 -1
  46. package/dist/global-skills/neon/SKILL.md +20 -27
  47. package/dist/global-skills/neon-ai-gateway/SKILL.md +2 -68
  48. package/dist/global-skills/neon-functions/SKILL.md +7 -7
  49. package/dist/global-skills/neon-object-storage/SKILL.md +2 -2
  50. package/dist/global-skills/neon-postgres/SKILL.md +5 -5
  51. package/dist/global-skills/neon-postgres-branches/SKILL.md +1 -1
  52. package/dist/global-skills/onboarding/SKILL.md +1 -1
  53. package/dist/global-skills/plan-my-idea/SKILL.md +1 -1
  54. package/dist/global-skills/publish-app/SKILL.md +1 -1
  55. package/dist/global-skills/publish-extension/SKILL.md +1 -1
  56. package/dist/global-skills/reset-password/SKILL.md +1 -1
  57. package/dist/global-skills/save-data/SKILL.md +1 -1
  58. package/dist/global-skills/setup-email/SKILL.md +1 -1
  59. package/dist/global-skills/setup-payments/SKILL.md +1 -1
  60. package/dist/global-skills/setup-sms/SKILL.md +1 -1
  61. package/dist/global-skills/sign-in-with-email-link/SKILL.md +1 -1
  62. package/dist/global-skills/sign-in-with-google/SKILL.md +1 -1
  63. package/dist/global-skills/sign-in-with-phone/SKILL.md +1 -1
  64. package/dist/global-skills/stripe-best-practices/SKILL.md +6 -11
  65. package/dist/global-skills/stripe-best-practices/references/billing.md +0 -5
  66. package/dist/global-skills/stripe-best-practices/references/payments.md +2 -4
  67. package/dist/global-skills/stripe-best-practices/references/tax.md +8 -78
  68. package/dist/global-skills/track-errors/SKILL.md +1 -1
  69. package/dist/global-skills/update-kit/SKILL.md +1 -1
  70. package/dist/global-skills/wire-auth/SKILL.md +1 -1
  71. package/dist/global-skills/wire-database/SKILL.md +1 -1
  72. package/dist/global-skills/wire-email/SKILL.md +1 -1
  73. package/dist/global-skills/wire-payments/SKILL.md +1 -1
  74. package/package.json +8 -8
  75. package/dist/global-skills/email-best-practices/.github/workflows/sync-skills.yml +0 -30
  76. package/dist/global-skills/email-best-practices/README.md +0 -63
  77. package/dist/global-skills/email-best-practices/references/accessibility.md +0 -189
  78. package/dist/global-skills/email-best-practices/references/compliance.md +0 -125
  79. package/dist/global-skills/email-best-practices/references/deliverability.md +0 -121
  80. package/dist/global-skills/email-best-practices/references/email-capture.md +0 -129
  81. package/dist/global-skills/email-best-practices/references/email-types.md +0 -173
  82. package/dist/global-skills/email-best-practices/references/list-management.md +0 -157
  83. package/dist/global-skills/email-best-practices/references/marketing-emails.md +0 -115
  84. package/dist/global-skills/email-best-practices/references/sending-reliability.md +0 -155
  85. package/dist/global-skills/email-best-practices/references/transactional-email-catalog.md +0 -418
  86. package/dist/global-skills/email-best-practices/references/transactional-emails.md +0 -92
  87. package/dist/global-skills/email-best-practices/references/webhooks-events.md +0 -167
  88. package/dist/global-skills/email-best-practices/tests/README.md +0 -35
  89. package/dist/global-skills/email-best-practices/tests/scenarios/01-spam-deliverability.md +0 -46
  90. package/dist/global-skills/email-best-practices/tests/scenarios/02-multi-region-compliance.md +0 -48
  91. package/dist/global-skills/email-best-practices/tests/scenarios/03-retry-idempotency.md +0 -36
  92. package/dist/global-skills/email-best-practices/tests/scenarios/04-webhook-bounce-handling.md +0 -52
  93. package/dist/global-skills/email-best-practices/tests/scenarios/05-new-saas-email-plan.md +0 -51
  94. package/dist/global-skills/neon-postgres/references/neon-sdk.md +0 -262
package/dist/bin.js CHANGED
@@ -5236,7 +5236,7 @@ var init_esm = __esm({
5236
5236
  });
5237
5237
 
5238
5238
  // src/bin.ts
5239
- import process29 from "process";
5239
+ import process32 from "process";
5240
5240
 
5241
5241
  // ../packages/core/src/accessGate.ts
5242
5242
  import { Data, Effect, Either } from "effect";
@@ -5688,9 +5688,9 @@ var walkPreferenceLadder = (walk) => Effect2.gen(function* () {
5688
5688
  });
5689
5689
 
5690
5690
  // src/cliRunner.ts
5691
- import { readFile as readFile23 } from "fs/promises";
5692
- import { dirname as dirname17, join as join52 } from "path";
5693
- import process28 from "process";
5691
+ import { readFile as readFile26 } from "fs/promises";
5692
+ import { dirname as dirname18, join as join55 } from "path";
5693
+ import process31 from "process";
5694
5694
  import { fileURLToPath as fileURLToPath9 } from "url";
5695
5695
 
5696
5696
  // src/commands/createSurfaceRegistry.ts
@@ -5756,6 +5756,7 @@ ${createSurfaceUsage}
5756
5756
  After your app exists (your AI coding tool drives these):
5757
5757
  vybekiit list-pieces \xB7 list-page-recipes \xB7 list-presets
5758
5758
  vybekiit add page-recipe <id> [--to=dir] [--dry-run] [--force]
5759
+ vybekiit add report-mode [--to=dir] [--dry-run] [--force]
5759
5760
  vybekiit apply-preset <id> [--cwd=dir] \xB7 verify-presets
5760
5761
  vybekiit scaffold backend \xB7 backend add-route|add-crud|add-upload|gen-contract
5761
5762
  vybekiit env wizard \xB7 sync-agent-layer \xB7 update path via your agent
@@ -5805,6 +5806,7 @@ Agent / kit:
5805
5806
  vybekiit list-page-recipes
5806
5807
  vybekiit list-presets
5807
5808
  vybekiit add page-recipe <id> [--to=dir] [--dry-run] [--force]
5809
+ vybekiit add report-mode [--to=dir] [--dry-run] [--force] (point & fix overlay into an existing app)
5808
5810
  vybekiit add (interactive: pick a ready piece)
5809
5811
  vybekiit apply-preset <feature> [--provider=supabase|neon|railway|mongodb|firebase|aws] [--cwd=dir] [--dry-run]
5810
5812
  vybekiit verify-presets [--fix] [--cwd=dir] [preset...]
@@ -5813,6 +5815,7 @@ Agent / kit:
5813
5815
  vybekiit live-work payments [--mode=demo|dogfood|buyer] [--vendor=lemon-squeezy|stripe|paypal] [--cwd=dir] [--no-pin] [--fresh]
5814
5816
  vybekiit lint-extension-skill <path> [--kind=buyer-goal|platform-wrapper|agent-skills-global]
5815
5817
  vybekiit doc-fallback <tech-id>
5818
+ vybekiit feedback status | feedback submit <draft> [--confirm]
5816
5819
  vybekiit dedup [--intent <desc>] [--target <file>] [--scope <dir>] [--index] [--json]
5817
5820
  vybekiit add bridge
5818
5821
  vybekiit env wizard
@@ -6288,6 +6291,23 @@ var GOAL_ENTRIES = [
6288
6291
  phrases: ["send emails", "email my users", "set up email"],
6289
6292
  skills: { web: "setup-email", mobile: null, extension: null, spa: null, backend: "wire-email" }
6290
6293
  },
6294
+ {
6295
+ id: "feedback",
6296
+ pageRecipeRequired: false,
6297
+ phrases: [
6298
+ "send feedback",
6299
+ "report a kit bug",
6300
+ "suggest a kit improvement",
6301
+ "the kit is confusing"
6302
+ ],
6303
+ skills: {
6304
+ web: "feedback",
6305
+ mobile: "feedback",
6306
+ extension: "feedback",
6307
+ spa: "feedback",
6308
+ backend: "feedback"
6309
+ }
6310
+ },
6291
6311
  {
6292
6312
  id: "doctor",
6293
6313
  phrases: ["it's broken", "nothing works", "get an error", "check my app"],
@@ -7208,6 +7228,88 @@ var renderToneSection = () => {
7208
7228
  return lines.join("\n");
7209
7229
  };
7210
7230
 
7231
+ // ../packages/agentKit/src/feedback/feedback.ts
7232
+ import { createHash } from "crypto";
7233
+ import { Schema as Schema2 } from "effect";
7234
+ var boundedText = (maximumLength) => Schema2.String.pipe(Schema2.minLength(1), Schema2.maxLength(maximumLength));
7235
+ var FeedbackDiagnosticsSchema = Schema2.Struct({
7236
+ agent: boundedText(100),
7237
+ agentVersion: boundedText(100),
7238
+ kitVersion: boundedText(100),
7239
+ operatingSystem: boundedText(200)
7240
+ });
7241
+ var FeedbackDraftSchema = Schema2.Struct({
7242
+ kind: Schema2.Literal("bug", "idea", "confusing"),
7243
+ buyerMessage: boundedText(4e3),
7244
+ agentSummary: boundedText(2e3),
7245
+ reproductionSteps: Schema2.Array(boundedText(500)).pipe(Schema2.maxItems(10)),
7246
+ template: Schema2.Literal("web", "mobile", "extension", "backend", "spa", "unknown"),
7247
+ trigger: Schema2.Literal("explicit", "automatic-suggestion"),
7248
+ diagnostics: FeedbackDiagnosticsSchema
7249
+ });
7250
+ var decodeFeedbackDraft = Schema2.decodeUnknownSync(FeedbackDraftSchema, {
7251
+ onExcessProperty: "error"
7252
+ });
7253
+ var REDACTION_PATTERNS = [
7254
+ // ghp_abc123... -> [removed]
7255
+ [/\b(?:gh[oprsu]_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,})\b/gu, "[removed]"],
7256
+ // sk-proj-abc123... -> [removed]
7257
+ [/\bsk-[A-Za-z0-9_-]{20,}\b/gu, "[removed]"],
7258
+ // AKIAIOSFODNN7EXAMPLE -> [removed]
7259
+ [/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/gu, "[removed]"],
7260
+ // eyJ...payload.signature -> [removed]
7261
+ [/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/gu, "[removed]"],
7262
+ // Authorization: Bearer abc -> Authorization: [removed]
7263
+ [/\bAuthorization\s*:\s*(?:Bearer|Basic)\s+[^\s,;]+/giu, "Authorization: [removed]"],
7264
+ // API_KEY=abc -> API_KEY=[removed]
7265
+ [
7266
+ /\b[A-Z0-9_-]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY)\s*[:=]\s*[^\s,;]+/giu,
7267
+ "[removed]"
7268
+ ],
7269
+ // postgres://buyer:secret@host/db -> [removed]
7270
+ [/\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis):\/\/[^\s,;]+/giu, "[removed]"],
7271
+ // buyer@example.com -> [removed]
7272
+ [/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/giu, "[removed]"],
7273
+ // C:\Users\buyer\project -> [removed]
7274
+ [/[A-Z]:\\(?:[^\\\s]+\\)*[^\\\s,;]+/giu, "[removed]"],
7275
+ // /Users/buyer/project -> [removed]
7276
+ [/(?:\/Users|\/home|\/root|\/private|\/tmp|\/var|\/opt)\/(?:[^/\s]+\/)*[^/\s,;]+/gu, "[removed]"],
7277
+ // buyer-mac.local -> [removed]
7278
+ [/\b[A-Z0-9][A-Z0-9-]*\.local\b/giu, "[removed]"]
7279
+ ];
7280
+ var redactText = (text2) => {
7281
+ let safeText = text2;
7282
+ for (const [pattern, replacement] of REDACTION_PATTERNS) {
7283
+ safeText = safeText.replace(pattern, replacement);
7284
+ }
7285
+ return safeText.replaceAll(/\s+/gu, " ").trim();
7286
+ };
7287
+ var redactFeedbackDraft = (draft) => ({
7288
+ ...draft,
7289
+ buyerMessage: redactText(draft.buyerMessage),
7290
+ agentSummary: redactText(draft.agentSummary),
7291
+ reproductionSteps: draft.reproductionSteps.map(redactText),
7292
+ diagnostics: {
7293
+ agent: redactText(draft.diagnostics.agent),
7294
+ agentVersion: redactText(draft.diagnostics.agentVersion),
7295
+ kitVersion: redactText(draft.diagnostics.kitVersion),
7296
+ operatingSystem: redactText(draft.diagnostics.operatingSystem)
7297
+ }
7298
+ });
7299
+ var fingerprintFeedbackDraft = (draft) => {
7300
+ const safeDraft = redactFeedbackDraft(draft);
7301
+ const canonicalDraft = JSON.stringify({
7302
+ kind: safeDraft.kind,
7303
+ buyerMessage: safeDraft.buyerMessage,
7304
+ agentSummary: safeDraft.agentSummary,
7305
+ reproductionSteps: safeDraft.reproductionSteps,
7306
+ template: safeDraft.template,
7307
+ trigger: safeDraft.trigger,
7308
+ diagnostics: safeDraft.diagnostics
7309
+ });
7310
+ return createHash("sha256").update(canonicalDraft).digest("hex");
7311
+ };
7312
+
7211
7313
  // ../packages/agentKit/src/lint/lintExtensionSkill.ts
7212
7314
  var BUYER_GOAL_REQUIRED = [
7213
7315
  { rule: "goal", pattern: /\*\*Goal:\*\*/ },
@@ -7452,7 +7554,7 @@ var renderBuyerSkillStub = (skillStem, buyerContent, template) => {
7452
7554
  return [
7453
7555
  "---",
7454
7556
  `name: ${skillStem}`,
7455
- `description: ${description}`,
7557
+ `description: ${JSON.stringify(description)}`,
7456
7558
  "metadata:",
7457
7559
  " vybekiit-generated: buyer-skill-stub",
7458
7560
  "---",
@@ -10549,13 +10651,13 @@ var parseCreateAppArgs = (argumentsToParse) => {
10549
10651
  return { ok: true, inputs: { surface: selectedSurface, destPath: destinationPath } };
10550
10652
  };
10551
10653
  var promptCreateSurface = async () => {
10552
- const { cancel: cancel4, intro: intro2, isCancel: isCancel5, outro, select: select3 } = await import("@clack/prompts");
10654
+ const { cancel: cancel4, intro: intro2, isCancel: isCancel6, outro, select: select3 } = await import("@clack/prompts");
10553
10655
  intro2("VybeKiit \u2014 create an app");
10554
10656
  const picked = await select3({
10555
10657
  message: "What are you building?",
10556
10658
  options: CREATE_SURFACE_PROMPT_OPTIONS
10557
10659
  });
10558
- if (isCancel5(picked) || typeof picked !== "string" || !isCreateSurface(picked)) {
10660
+ if (isCancel6(picked) || typeof picked !== "string" || !isCreateSurface(picked)) {
10559
10661
  cancel4("Cancelled.");
10560
10662
  return null;
10561
10663
  }
@@ -10925,13 +11027,13 @@ var writeTemplateRequired = (flags) => {
10925
11027
  return 1;
10926
11028
  };
10927
11029
  var promptForDropInputs = async (parsed) => {
10928
- const { confirm: confirm2, intro: intro2, isCancel: isCancel5, select: select3, text: text2, cancel: cancel4 } = await import("@clack/prompts");
11030
+ const { confirm: confirm3, intro: intro2, isCancel: isCancel6, select: select3, text: text2, cancel: cancel4 } = await import("@clack/prompts");
10929
11031
  intro2("VybeKiit: drop a template");
10930
11032
  const picked = await select3({
10931
11033
  message: "Which template?",
10932
11034
  options: DROP_TEMPLATE_OPTIONS
10933
11035
  });
10934
- if (isCancel5(picked) || typeof picked !== "string" || !isTemplateName(picked)) {
11036
+ if (isCancel6(picked) || typeof picked !== "string" || !isTemplateName(picked)) {
10935
11037
  cancel4("Cancelled.");
10936
11038
  return null;
10937
11039
  }
@@ -10944,17 +11046,17 @@ var promptForDropInputs = async (parsed) => {
10944
11046
  defaultValue: `./${picked}`,
10945
11047
  validate: (value) => typeof value === "string" && value.trim() !== "" ? void 0 : "Path is required"
10946
11048
  });
10947
- if (isCancel5(dest) || typeof dest !== "string") {
11049
+ if (isCancel6(dest) || typeof dest !== "string") {
10948
11050
  cancel4("Cancelled.");
10949
11051
  return null;
10950
11052
  }
10951
11053
  destPath = dest;
10952
11054
  }
10953
11055
  const mode = dropMode(parsed.flags);
10954
- const confirmed = await confirm2({
11056
+ const confirmed = await confirm3({
10955
11057
  message: `Drop "${picked}" -> ${resolve5(destPath)}${mode === "new" ? "" : ` (${mode})`}?`
10956
11058
  });
10957
- if (isCancel5(confirmed) || !confirmed) {
11059
+ if (isCancel6(confirmed) || !confirmed) {
10958
11060
  cancel4("Cancelled.");
10959
11061
  return null;
10960
11062
  }
@@ -11149,19 +11251,255 @@ var runDrop = async (args) => {
11149
11251
  }
11150
11252
  };
11151
11253
 
11254
+ // src/commands/feedbackCmd.ts
11255
+ import process7 from "process";
11256
+ import { confirm, isCancel } from "@clack/prompts";
11257
+ import open from "open";
11258
+
11259
+ // src/feedback/feedbackClient.ts
11260
+ import { Schema as Schema3 } from "effect";
11261
+ var DeviceLoginSchema = Schema3.Struct({
11262
+ deviceCode: Schema3.String,
11263
+ userCode: Schema3.String,
11264
+ verificationUri: Schema3.String,
11265
+ expiresIn: Schema3.Number,
11266
+ interval: Schema3.Number
11267
+ });
11268
+ var IntakeSessionStateSchema = Schema3.Union(
11269
+ Schema3.Struct({
11270
+ status: Schema3.Literal("pending"),
11271
+ retryAfter: Schema3.optional(Schema3.Number)
11272
+ }),
11273
+ Schema3.Struct({ status: Schema3.Literal("ready"), session: Schema3.String }),
11274
+ Schema3.Struct({ status: Schema3.Literal("denied"), message: Schema3.String })
11275
+ );
11276
+ var FeedbackReceiptSchema = Schema3.Struct({ reference: Schema3.String });
11277
+ var resolveBaseUrl = (configuredUrl) => {
11278
+ const baseUrl = configuredUrl || process.env.VYBEKIIT_API_URL || "https://vybekiit.com/api";
11279
+ const parsedUrl = new URL(baseUrl);
11280
+ const localDevelopment = parsedUrl.hostname === "localhost" || parsedUrl.hostname === "127.0.0.1";
11281
+ if (parsedUrl.protocol !== "https:" && !localDevelopment) {
11282
+ throw new Error("Feedback intake requires HTTPS.");
11283
+ }
11284
+ return baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
11285
+ };
11286
+ var readJson = async (response, schema) => {
11287
+ if (!response.ok) {
11288
+ throw new Error(`Feedback intake returned ${response.status}.`);
11289
+ }
11290
+ return Schema3.decodeUnknownSync(schema)(await response.json());
11291
+ };
11292
+ var createFeedbackIntakeClient = (options = {}) => {
11293
+ const baseUrl = resolveBaseUrl(options.baseUrl);
11294
+ const fetchRequest = options.fetch || globalThis.fetch;
11295
+ return {
11296
+ createDeviceLogin: async () => {
11297
+ const response = await fetchRequest(`${baseUrl}/feedback/auth/device`, { method: "POST" });
11298
+ return await readJson(response, DeviceLoginSchema);
11299
+ },
11300
+ pollDeviceLogin: async (deviceCode) => {
11301
+ const response = await fetchRequest(`${baseUrl}/feedback/auth/poll`, {
11302
+ method: "POST",
11303
+ headers: { "content-type": "application/json" },
11304
+ body: JSON.stringify({ deviceCode })
11305
+ });
11306
+ return await readJson(response, IntakeSessionStateSchema);
11307
+ },
11308
+ submit: async ({ session, draft }) => {
11309
+ const response = await fetchRequest(`${baseUrl}/feedback/report`, {
11310
+ method: "POST",
11311
+ headers: {
11312
+ authorization: `Bearer ${session}`,
11313
+ "content-type": "application/json"
11314
+ },
11315
+ body: JSON.stringify(redactFeedbackDraft(draft))
11316
+ });
11317
+ return await readJson(response, FeedbackReceiptSchema);
11318
+ }
11319
+ };
11320
+ };
11321
+
11322
+ // src/feedback/feedbackFiles.ts
11323
+ import { chmod, lstat as lstat2, mkdir as mkdir6, readFile as readFile7, realpath, rename, writeFile as writeFile6 } from "fs/promises";
11324
+ import { isAbsolute, join as join14, relative } from "path";
11325
+ var FeedbackFileError = class extends Error {
11326
+ code;
11327
+ constructor(code, message, cause) {
11328
+ super(message, { cause });
11329
+ this.name = "FeedbackFileError";
11330
+ this.code = code;
11331
+ }
11332
+ };
11333
+ var isBeneath = (candidatePath, parentPath) => {
11334
+ const pathFromParent = relative(parentPath, candidatePath);
11335
+ return pathFromParent !== "" && !pathFromParent.startsWith("..") && !isAbsolute(pathFromParent);
11336
+ };
11337
+ var readFeedbackDraft = async (draftPath, projectRoot) => {
11338
+ const draftsDirectory = await realpath(join14(projectRoot, ".vybekiit", "feedback-drafts"));
11339
+ const draftEntry = await lstat2(draftPath).catch(() => void 0);
11340
+ if (!draftEntry?.isFile() || draftEntry.isSymbolicLink()) {
11341
+ throw new FeedbackFileError(
11342
+ "invalid_draft_path",
11343
+ "Choose a feedback draft created in this app."
11344
+ );
11345
+ }
11346
+ const resolvedDraftPath = await realpath(draftPath);
11347
+ if (!isBeneath(resolvedDraftPath, draftsDirectory)) {
11348
+ throw new FeedbackFileError(
11349
+ "invalid_draft_path",
11350
+ "Choose a feedback draft created in this app."
11351
+ );
11352
+ }
11353
+ if (draftEntry.size > 32 * 1024) {
11354
+ throw new FeedbackFileError(
11355
+ "draft_too_large",
11356
+ "This feedback draft is too large to send safely."
11357
+ );
11358
+ }
11359
+ try {
11360
+ return decodeFeedbackDraft(JSON.parse(await readFile7(resolvedDraftPath, "utf8")));
11361
+ } catch (error) {
11362
+ if (error instanceof FeedbackFileError) {
11363
+ throw error;
11364
+ }
11365
+ throw new FeedbackFileError(
11366
+ "invalid_draft",
11367
+ "This feedback draft could not be read safely.",
11368
+ error
11369
+ );
11370
+ }
11371
+ };
11372
+ var recordFeedbackSubmission = async (projectRoot, submission) => {
11373
+ const feedbackDirectory = join14(projectRoot, ".vybekiit");
11374
+ const submissionsPath = join14(feedbackDirectory, "feedback-submissions.json");
11375
+ const temporaryPath = `${submissionsPath}.${process.pid}.tmp`;
11376
+ await mkdir6(feedbackDirectory, { recursive: true, mode: 448 });
11377
+ let submissions = [];
11378
+ try {
11379
+ const storedSubmissions = JSON.parse(await readFile7(submissionsPath, "utf8"));
11380
+ if (Array.isArray(storedSubmissions)) {
11381
+ submissions = storedSubmissions.filter(
11382
+ (entry) => typeof entry === "object" && entry !== null && "fingerprint" in entry && typeof entry.fingerprint === "string" && "reference" in entry && typeof entry.reference === "string" && "submittedAt" in entry && typeof entry.submittedAt === "string"
11383
+ );
11384
+ }
11385
+ } catch {
11386
+ submissions = [];
11387
+ }
11388
+ await writeFile6(temporaryPath, `${JSON.stringify([...submissions, submission], null, 2)}
11389
+ `, {
11390
+ mode: 384
11391
+ });
11392
+ await rename(temporaryPath, submissionsPath);
11393
+ await chmod(submissionsPath, 384);
11394
+ };
11395
+
11396
+ // src/commands/feedbackCmd.ts
11397
+ var defaultDependencies = () => ({
11398
+ projectRoot: process7.cwd(),
11399
+ interactive: isInteractive(),
11400
+ confirm: async () => {
11401
+ const answer = await confirm({ message: "Send this private feedback report to VybeKiit?" });
11402
+ return !isCancel(answer) && answer;
11403
+ },
11404
+ openBrowser: open,
11405
+ sleep: async (milliseconds) => await new Promise((resolve13) => setTimeout(resolve13, milliseconds)),
11406
+ writeOutput: (message) => process7.stdout.write(`${message}
11407
+ `),
11408
+ writeError: (message) => process7.stderr.write(`${message}
11409
+ `),
11410
+ now: () => /* @__PURE__ */ new Date(),
11411
+ client: createFeedbackIntakeClient()
11412
+ });
11413
+ var waitForSession = async (deviceCode, interval, expiresIn, dependencies) => {
11414
+ const expiresAt = dependencies.now().getTime() + expiresIn * 1e3;
11415
+ let pollingInterval = interval;
11416
+ while (dependencies.now().getTime() < expiresAt) {
11417
+ const sessionState = await dependencies.client.pollDeviceLogin(deviceCode);
11418
+ if (sessionState.status !== "pending") {
11419
+ return sessionState;
11420
+ }
11421
+ if (sessionState.retryAfter) {
11422
+ pollingInterval += sessionState.retryAfter;
11423
+ }
11424
+ await dependencies.sleep(pollingInterval * 1e3);
11425
+ }
11426
+ return { status: "denied", message: "The sign-in code expired. Run /feedback again." };
11427
+ };
11428
+ var showFeedbackStatus = (dependencies) => {
11429
+ dependencies.writeOutput(
11430
+ JSON.stringify({ ok: true, drafts: ".vybekiit/feedback-drafts", confirmationRequired: true })
11431
+ );
11432
+ return 0;
11433
+ };
11434
+ var showFeedbackUsage = (dependencies) => {
11435
+ dependencies.writeError("Usage: vybekiit feedback status | feedback submit <draft> [--confirm]");
11436
+ return 1;
11437
+ };
11438
+ var runFeedback = async (args, suppliedDependencies) => {
11439
+ const dependencies = suppliedDependencies || defaultDependencies();
11440
+ const [action, draftPath] = args;
11441
+ if (action === "status") {
11442
+ return showFeedbackStatus(dependencies);
11443
+ }
11444
+ if (action !== "submit" || !draftPath) {
11445
+ return showFeedbackUsage(dependencies);
11446
+ }
11447
+ const confirmed = dependencies.interactive ? await dependencies.confirm() : args.includes("--confirm");
11448
+ if (!confirmed) {
11449
+ if (!dependencies.interactive) {
11450
+ dependencies.writeError(
11451
+ "Add --confirm only after the buyer has approved sending the report."
11452
+ );
11453
+ return 1;
11454
+ }
11455
+ dependencies.writeOutput("Feedback was not sent. Your draft is still saved.");
11456
+ return 0;
11457
+ }
11458
+ try {
11459
+ const draft = await readFeedbackDraft(draftPath, dependencies.projectRoot);
11460
+ const deviceLogin = await dependencies.client.createDeviceLogin();
11461
+ dependencies.writeOutput(
11462
+ `Sign in to send feedback: ${deviceLogin.verificationUri} code ${deviceLogin.userCode}`
11463
+ );
11464
+ await dependencies.openBrowser(deviceLogin.verificationUri);
11465
+ const sessionState = await waitForSession(
11466
+ deviceLogin.deviceCode,
11467
+ deviceLogin.interval,
11468
+ deviceLogin.expiresIn,
11469
+ dependencies
11470
+ );
11471
+ if (sessionState.status !== "ready") {
11472
+ dependencies.writeError(sessionState.message);
11473
+ return 1;
11474
+ }
11475
+ const receipt = await dependencies.client.submit({ session: sessionState.session, draft });
11476
+ await recordFeedbackSubmission(dependencies.projectRoot, {
11477
+ fingerprint: fingerprintFeedbackDraft(draft),
11478
+ reference: receipt.reference,
11479
+ submittedAt: dependencies.now().toISOString()
11480
+ });
11481
+ dependencies.writeOutput(JSON.stringify({ ok: true, reference: receipt.reference }));
11482
+ return 0;
11483
+ } catch (error) {
11484
+ const detail = error instanceof Error ? error.message : "The feedback service is unavailable.";
11485
+ dependencies.writeError(`Feedback was not sent. Your draft is still saved. ${detail}`);
11486
+ return 1;
11487
+ }
11488
+ };
11489
+
11152
11490
  // src/commands/init.ts
11153
- import { join as join18 } from "path";
11491
+ import { join as join19 } from "path";
11154
11492
 
11155
11493
  // src/commands/initAssets.ts
11156
11494
  import { execFile as execFile5 } from "child_process";
11157
- import { cp as cp4, mkdir as mkdir6, readdir as readdir7, readFile as readFile8, writeFile as writeFile6 } from "fs/promises";
11158
- import { dirname as dirname8, join as join15 } from "path";
11495
+ import { cp as cp4, mkdir as mkdir7, readdir as readdir7, readFile as readFile9, writeFile as writeFile7 } from "fs/promises";
11496
+ import { dirname as dirname8, join as join16 } from "path";
11159
11497
  import { fileURLToPath as fileURLToPath5 } from "url";
11160
11498
  import { promisify as promisify5 } from "util";
11161
11499
 
11162
11500
  // src/commands/initTypes.ts
11163
- import { access as access8, readFile as readFile7 } from "fs/promises";
11164
- import { join as join14 } from "path";
11501
+ import { access as access8, readFile as readFile8 } from "fs/promises";
11502
+ import { join as join15 } from "path";
11165
11503
  var pathExists4 = async (path) => {
11166
11504
  try {
11167
11505
  await access8(path);
@@ -11172,7 +11510,7 @@ var pathExists4 = async (path) => {
11172
11510
  };
11173
11511
  var readInitPackageJson = async (cwd) => {
11174
11512
  try {
11175
- const raw = await readFile7(join14(cwd, "package.json"), "utf8");
11513
+ const raw = await readFile8(join15(cwd, "package.json"), "utf8");
11176
11514
  return JSON.parse(raw);
11177
11515
  } catch {
11178
11516
  return null;
@@ -11183,22 +11521,22 @@ var readInitPackageJson = async (cwd) => {
11183
11521
  var execFileAsync5 = promisify5(execFile5);
11184
11522
  var HERE5 = dirname8(fileURLToPath5(import.meta.url));
11185
11523
  var copyClaudeHooks = async (cwd, templateDir) => {
11186
- const claudeSource = join15(templateDir, ".claude");
11524
+ const claudeSource = join16(templateDir, ".claude");
11187
11525
  if (!await pathExists4(claudeSource)) {
11188
11526
  process.stdout.write(" \u26A0\uFE0F Could not copy .claude hooks (source missing)\n");
11189
11527
  return;
11190
11528
  }
11191
- await cp4(claudeSource, join15(cwd, ".claude"), { recursive: true, force: true });
11529
+ await cp4(claudeSource, join16(cwd, ".claude"), { recursive: true, force: true });
11192
11530
  process.stdout.write(" \u2705 .claude/settings.json + hooks\n");
11193
11531
  };
11194
11532
  var copyWorkflows = async (cwd, templateDir, pm) => {
11195
- const workflowsDir = join15(cwd, ".github", "workflows");
11196
- const workflowsSource = join15(templateDir, ".github", "workflows");
11533
+ const workflowsDir = join16(cwd, ".github", "workflows");
11534
+ const workflowsSource = join16(templateDir, ".github", "workflows");
11197
11535
  if (!await pathExists4(workflowsSource)) {
11198
11536
  process.stdout.write(" \u26A0\uFE0F Could not copy workflows (source missing)\n");
11199
11537
  return;
11200
11538
  }
11201
- await mkdir6(workflowsDir, { recursive: true });
11539
+ await mkdir7(workflowsDir, { recursive: true });
11202
11540
  await cp4(workflowsSource, workflowsDir, { recursive: true, force: true });
11203
11541
  if (pm !== "pnpm") {
11204
11542
  await adaptWorkflows(workflowsDir, pm);
@@ -11206,23 +11544,23 @@ var copyWorkflows = async (cwd, templateDir, pm) => {
11206
11544
  process.stdout.write(" \u2705 .github/workflows/ (CI pipeline)\n");
11207
11545
  };
11208
11546
  var copyPrePushHook = async (cwd, templateDir) => {
11209
- const huskySource = join15(templateDir, ".husky", "pre-push");
11547
+ const huskySource = join16(templateDir, ".husky", "pre-push");
11210
11548
  if (!await pathExists4(huskySource)) {
11211
11549
  process.stdout.write(" \u26A0\uFE0F Could not copy pre-push hook\n");
11212
11550
  return;
11213
11551
  }
11214
- const huskyDir = join15(cwd, ".husky");
11215
- await mkdir6(huskyDir, { recursive: true });
11216
- await cp4(huskySource, join15(huskyDir, "pre-push"), { force: true });
11552
+ const huskyDir = join16(cwd, ".husky");
11553
+ await mkdir7(huskyDir, { recursive: true });
11554
+ await cp4(huskySource, join16(huskyDir, "pre-push"), { force: true });
11217
11555
  process.stdout.write(" \u2705 .husky/pre-push\n");
11218
11556
  };
11219
11557
  var copySecurityFile = async (cwd, templateDir) => {
11220
- const dest = join15(cwd, "SECURITY.md");
11558
+ const dest = join16(cwd, "SECURITY.md");
11221
11559
  if (await pathExists4(dest)) {
11222
11560
  process.stdout.write(" \u2713 SECURITY.md (already exists)\n");
11223
11561
  return;
11224
11562
  }
11225
- const source = join15(templateDir, "SECURITY.md");
11563
+ const source = join16(templateDir, "SECURITY.md");
11226
11564
  if (!await pathExists4(source)) {
11227
11565
  process.stdout.write(" \u26A0\uFE0F Could not copy SECURITY.md\n");
11228
11566
  return;
@@ -11231,14 +11569,14 @@ var copySecurityFile = async (cwd, templateDir) => {
11231
11569
  process.stdout.write(" \u2705 SECURITY.md\n");
11232
11570
  };
11233
11571
  var createDevScriptsDir = async (cwd) => {
11234
- const devScriptsDir = join15(cwd, "dev-scripts");
11235
- const gitkeepPath = join15(devScriptsDir, ".gitkeep");
11236
- await mkdir6(devScriptsDir, { recursive: true });
11572
+ const devScriptsDir = join16(cwd, "dev-scripts");
11573
+ const gitkeepPath = join16(devScriptsDir, ".gitkeep");
11574
+ await mkdir7(devScriptsDir, { recursive: true });
11237
11575
  if (await pathExists4(gitkeepPath)) {
11238
11576
  process.stdout.write(" \u2713 dev-scripts/ (already exists)\n");
11239
11577
  return;
11240
11578
  }
11241
- await writeFile6(
11579
+ await writeFile7(
11242
11580
  gitkeepPath,
11243
11581
  "# Local-only dev scripts - gitignored, never committed to the repo.\n",
11244
11582
  { flag: "wx" }
@@ -11247,8 +11585,8 @@ var createDevScriptsDir = async (cwd) => {
11247
11585
  };
11248
11586
  var generatePlatformConfigs = async (cwd) => {
11249
11587
  const possiblePaths = [
11250
- join15(cwd, ".claude", "platforms", "generate-platform-configs.sh"),
11251
- join15(
11588
+ join16(cwd, ".claude", "platforms", "generate-platform-configs.sh"),
11589
+ join16(
11252
11590
  HERE5,
11253
11591
  "..",
11254
11592
  "..",
@@ -11276,12 +11614,12 @@ var generatePlatformConfigs = async (cwd) => {
11276
11614
  return;
11277
11615
  }
11278
11616
  }
11279
- const agentsPath = join15(cwd, "AGENTS.md");
11617
+ const agentsPath = join16(cwd, "AGENTS.md");
11280
11618
  if (await pathExists4(agentsPath)) {
11281
11619
  process.stdout.write(" \u2713 AGENTS.md (already exists)\n");
11282
11620
  return;
11283
11621
  }
11284
- await writeFile6(
11622
+ await writeFile7(
11285
11623
  agentsPath,
11286
11624
  "# Agent Instructions\n\nThis project uses VybeKiit conventions.\n\nSee .claude/hooks/ for enforced rules.\n"
11287
11625
  );
@@ -11314,19 +11652,19 @@ var adaptWorkflows = async (dir, pm) => {
11314
11652
  const workflowFiles = files.filter((file) => file.endsWith(".yml"));
11315
11653
  await Promise.all(
11316
11654
  workflowFiles.map(async (file) => {
11317
- const path = join15(dir, file);
11318
- let content = await readFile8(path, "utf8");
11655
+ const path = join16(dir, file);
11656
+ let content = await readFile9(path, "utf8");
11319
11657
  for (const [from, to] of Object.entries(replacements[pm])) {
11320
11658
  content = content.replaceAll(from, to);
11321
11659
  }
11322
- await writeFile6(path, content);
11660
+ await writeFile7(path, content);
11323
11661
  })
11324
11662
  );
11325
11663
  };
11326
11664
 
11327
11665
  // src/commands/initDetect.ts
11328
11666
  import { existsSync as existsSync4 } from "fs";
11329
- import { join as join16 } from "path";
11667
+ import { join as join17 } from "path";
11330
11668
  var packageManagerFromManifest = (value) => {
11331
11669
  if (value === void 0 || value === "") {
11332
11670
  return null;
@@ -11353,7 +11691,7 @@ var detectPackageManager = async (cwd) => {
11353
11691
  ["package-lock.json", "npm"]
11354
11692
  ];
11355
11693
  const lockfileMatches = checks.map(([file, pm]) => ({
11356
- found: existsSync4(join16(cwd, file)),
11694
+ found: existsSync4(join17(cwd, file)),
11357
11695
  pm
11358
11696
  }));
11359
11697
  const match = lockfileMatches.find((entry) => entry.found);
@@ -11420,15 +11758,15 @@ var writeInitSuccess = (pm) => {
11420
11758
  };
11421
11759
 
11422
11760
  // src/commands/initPatches.ts
11423
- import { readFile as readFile9, writeFile as writeFile7 } from "fs/promises";
11424
- import { join as join17 } from "path";
11761
+ import { readFile as readFile10, writeFile as writeFile8 } from "fs/promises";
11762
+ import { join as join18 } from "path";
11425
11763
  var patchGitignore = async (cwd) => {
11426
- const gitignorePath = join17(cwd, ".gitignore");
11427
- const content = await pathExists4(gitignorePath) ? await readFile9(gitignorePath, "utf8") : "";
11764
+ const gitignorePath = join18(cwd, ".gitignore");
11765
+ const content = await pathExists4(gitignorePath) ? await readFile10(gitignorePath, "utf8") : "";
11428
11766
  const needed = ["dev-scripts/", ".env", ".env.*", "!.env.example"];
11429
11767
  const additions = needed.filter((pattern) => !content.includes(pattern));
11430
11768
  if (additions.length > 0) {
11431
- await writeFile7(gitignorePath, `${content}
11769
+ await writeFile8(gitignorePath, `${content}
11432
11770
  # VybeKiit guardrails
11433
11771
  ${additions.join("\n")}
11434
11772
  `);
@@ -11438,7 +11776,7 @@ ${additions.join("\n")}
11438
11776
  process.stdout.write(" \u2713 .gitignore (already has required entries)\n");
11439
11777
  };
11440
11778
  var patchPackageScripts = async (cwd, pm) => {
11441
- const pkgPath = join17(cwd, "package.json");
11779
+ const pkgPath = join18(cwd, "package.json");
11442
11780
  const pkg = await readInitPackageJson(cwd);
11443
11781
  if (pkg === null) {
11444
11782
  process.stdout.write(" \u26A0\uFE0F package.json scripts skipped (package.json missing)\n");
@@ -11452,7 +11790,7 @@ var patchPackageScripts = async (cwd, pm) => {
11452
11790
  ...scripts.verify === void 0 ? { verify: `${pm} run check:ci && ${pm} run typecheck && ${pm} run test` } : {}
11453
11791
  };
11454
11792
  if (Object.keys(patchedScripts).length !== Object.keys(scripts).length) {
11455
- await writeFile7(pkgPath, `${JSON.stringify({ ...pkg, scripts: patchedScripts }, null, 2)}
11793
+ await writeFile8(pkgPath, `${JSON.stringify({ ...pkg, scripts: patchedScripts }, null, 2)}
11456
11794
  `);
11457
11795
  process.stdout.write(" \u2705 package.json scripts patched (check:ci, typecheck, verify)\n");
11458
11796
  return;
@@ -11463,7 +11801,7 @@ var patchPackageScripts = async (cwd, pm) => {
11463
11801
  // src/commands/init.ts
11464
11802
  var runInit = async (args) => {
11465
11803
  const [targetPath] = args;
11466
- const cwd = targetPath !== void 0 && targetPath !== "" ? join18(process.cwd(), targetPath) : process.cwd();
11804
+ const cwd = targetPath !== void 0 && targetPath !== "" ? join19(process.cwd(), targetPath) : process.cwd();
11467
11805
  process.stdout.write("\u{1F512} VybeKiit init: bootstrapping security guardrails...\n");
11468
11806
  process.stdout.write("\n");
11469
11807
  const pm = await detectPackageManager(cwd);
@@ -11482,7 +11820,7 @@ var runInit = async (args) => {
11482
11820
  try {
11483
11821
  const { cleanup: resolvedCleanup, source } = await resolveTemplatesSource(projectType);
11484
11822
  cleanup = resolvedCleanup;
11485
- const templateDir = join18(source, projectType);
11823
+ const templateDir = join19(source, projectType);
11486
11824
  await copyClaudeHooks(cwd, templateDir);
11487
11825
  await copyWorkflows(cwd, templateDir, pm);
11488
11826
  await copyPrePushHook(cwd, templateDir);
@@ -11504,7 +11842,7 @@ var runInit = async (args) => {
11504
11842
  };
11505
11843
 
11506
11844
  // src/commands/lintExtensionSkill.ts
11507
- import { readFile as readFile10 } from "fs/promises";
11845
+ import { readFile as readFile11 } from "fs/promises";
11508
11846
  var resolveExtensionSkillKind = (path, explicit) => {
11509
11847
  if (explicit === "buyer-goal" || explicit === "platform-wrapper" || explicit === "agent-skills-global") {
11510
11848
  return explicit;
@@ -11549,7 +11887,7 @@ var runLintExtensionSkill = async (args) => {
11549
11887
  }
11550
11888
  let content;
11551
11889
  try {
11552
- content = await readFile10(path, "utf8");
11890
+ content = await readFile11(path, "utf8");
11553
11891
  } catch {
11554
11892
  return {
11555
11893
  json: JSON.stringify({ ok: false, error: `Cannot read file: ${path}` }),
@@ -11565,7 +11903,7 @@ var runLintExtensionSkill = async (args) => {
11565
11903
 
11566
11904
  // src/commands/liveWorkDataCmd.ts
11567
11905
  import { resolve as resolve7 } from "path";
11568
- import process7 from "process";
11906
+ import process8 from "process";
11569
11907
 
11570
11908
  // ../packages/db/src/types.ts
11571
11909
  import { Data as Data3 } from "effect";
@@ -14548,9 +14886,9 @@ import { Effect as Effect12, Either as Either2 } from "effect";
14548
14886
 
14549
14887
  // ../packages/core/src/node.ts
14550
14888
  import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
14551
- import { join as join19 } from "path";
14889
+ import { join as join20 } from "path";
14552
14890
  var loadEnvFile = (cwd, filename = ".env") => {
14553
- const path = join19(cwd, filename);
14891
+ const path = join20(cwd, filename);
14554
14892
  if (!existsSync5(path)) {
14555
14893
  return {};
14556
14894
  }
@@ -14575,7 +14913,7 @@ var mergeEnvFile = (processEnv, fileEnv) => ({ ...processEnv, ...fileEnv });
14575
14913
 
14576
14914
  // src/doctor/writeEnvKeys.ts
14577
14915
  import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
14578
- import { join as join20 } from "path";
14916
+ import { join as join21 } from "path";
14579
14917
  var TRAILING_NEWLINES_PATTERN = /\n*$/;
14580
14918
  var renderEnvValue = (value) => {
14581
14919
  if (value.includes(" ")) {
@@ -14592,7 +14930,7 @@ var replaceEnvLine = (lines, key, newLine) => {
14592
14930
  return true;
14593
14931
  };
14594
14932
  var writeEnvKeys = (cwd, keys) => {
14595
- const path = join20(cwd, ".env");
14933
+ const path = join21(cwd, ".env");
14596
14934
  const existing = existsSync6(path) ? readFileSync4(path, "utf8") : "";
14597
14935
  const lines = existing.length > 0 ? existing.split("\n") : [];
14598
14936
  for (const [key, value] of Object.entries(keys)) {
@@ -14623,7 +14961,7 @@ var parseLiveWorkDataFlags = (args) => {
14623
14961
  const modeRaw = readFlagValue(args, "mode") ?? "demo";
14624
14962
  const vendorRaw = readFlagValue(args, "vendor");
14625
14963
  const cwdRaw = readFlagValue(args, "cwd");
14626
- const cwd = resolve7(process7.cwd(), cwdRaw === void 0 || cwdRaw === "" ? "." : cwdRaw);
14964
+ const cwd = resolve7(process8.cwd(), cwdRaw === void 0 || cwdRaw === "" ? "." : cwdRaw);
14627
14965
  if (!isLiveWorkMode(modeRaw)) {
14628
14966
  return {
14629
14967
  mode: "demo",
@@ -14686,7 +15024,7 @@ var toFailurePayload = (error) => {
14686
15024
  }
14687
15025
  return failure;
14688
15026
  };
14689
- var resolveLiveWorkEnv = (cwd) => mergeEnv(process7.env, loadEnvFile2(cwd));
15027
+ var resolveLiveWorkEnv = (cwd) => mergeEnv(process8.env, loadEnvFile2(cwd));
14690
15028
  var writeDataPin = (cwd, keys) => Effect12.try({
14691
15029
  try: () => {
14692
15030
  writeEnvKeys2(cwd, keys);
@@ -14742,7 +15080,7 @@ var runLiveWorkData = async (args) => {
14742
15080
 
14743
15081
  // src/commands/liveWorkHostCmd.ts
14744
15082
  import { resolve as resolve8 } from "path";
14745
- import process8 from "process";
15083
+ import process9 from "process";
14746
15084
 
14747
15085
  // ../packages/deploy/src/deployEffect.ts
14748
15086
  import { Effect as Effect13 } from "effect";
@@ -14759,7 +15097,7 @@ var failDeploy = (code, message) => Effect13.fail(deployError(code, message));
14759
15097
  // ../packages/deploy/src/liveWork/cloudflareProvision.ts
14760
15098
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
14761
15099
  import { tmpdir as tmpdir3 } from "os";
14762
- import { join as join21 } from "path";
15100
+ import { join as join22 } from "path";
14763
15101
  import { Effect as Effect14 } from "effect";
14764
15102
 
14765
15103
  // ../packages/deploy/src/liveWork/types.ts
@@ -14817,10 +15155,10 @@ var defaultLiveWorkProjectName = (prefix = "vybekiit-lw") => {
14817
15155
  return `${prefix}-${stamp}`.toLowerCase().replaceAll(/[^a-z0-9-]/g, "-").slice(0, 58);
14818
15156
  };
14819
15157
  var writeDemoStaticSite = (parentDir) => {
14820
- const buildDir = join21(parentDir, "site");
15158
+ const buildDir = join22(parentDir, "site");
14821
15159
  mkdirSync2(buildDir, { recursive: true });
14822
15160
  writeFileSync3(
14823
- join21(buildDir, "index.html"),
15161
+ join22(buildDir, "index.html"),
14824
15162
  `<!doctype html><html lang="en"><head><meta charset="utf-8"/><title>VybeKiit Live work</title></head><body><main data-vybekiit-live-work="1"><h1>Live work host OK</h1></main></body></html>
14825
15163
  `,
14826
15164
  "utf8"
@@ -14897,7 +15235,7 @@ var createCloudflarePagesHost = (options) => Effect14.gen(function* () {
14897
15235
  })
14898
15236
  );
14899
15237
  }
14900
- const parent = options.cwd ?? join21(tmpdir3(), defaultLiveWorkProjectName("vybekiit-lw-site"));
15238
+ const parent = options.cwd ?? join22(tmpdir3(), defaultLiveWorkProjectName("vybekiit-lw-site"));
14901
15239
  mkdirSync2(parent, { recursive: true });
14902
15240
  buildDir = writeDemoStaticSite(parent);
14903
15241
  }
@@ -14998,7 +15336,7 @@ var mapCloudflareCause = (cause) => {
14998
15336
  // ../packages/deploy/src/liveWork/githubPagesProvision.ts
14999
15337
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync5 } from "fs";
15000
15338
  import { tmpdir as tmpdir4 } from "os";
15001
- import { join as join22 } from "path";
15339
+ import { join as join23 } from "path";
15002
15340
  import { Effect as Effect15 } from "effect";
15003
15341
  var readGithubToken = (env) => {
15004
15342
  for (const key of ["GITHUB_TOKEN", "GH_TOKEN"]) {
@@ -15126,7 +15464,7 @@ var createGithubPagesHost = (options) => Effect15.gen(function* () {
15126
15464
  );
15127
15465
  }
15128
15466
  if (options.createPages === void 0) {
15129
- const parent = options.cwd ?? join22(tmpdir4(), defaultLiveWorkProjectName("vybekiit-lw-gp-site"));
15467
+ const parent = options.cwd ?? join23(tmpdir4(), defaultLiveWorkProjectName("vybekiit-lw-gp-site"));
15130
15468
  mkdirSync3(parent, { recursive: true });
15131
15469
  buildDir = writeDemoStaticSite(parent);
15132
15470
  }
@@ -15183,7 +15521,7 @@ var createGithubPagesHost = (options) => Effect15.gen(function* () {
15183
15521
  if (!createRepo.ok) {
15184
15522
  throw mapGithubHttp(createRepo.status, createText, "github_pages_repo_create_failed");
15185
15523
  }
15186
- const indexPath = join22(buildDir, "index.html");
15524
+ const indexPath = join23(buildDir, "index.html");
15187
15525
  let indexHtml;
15188
15526
  try {
15189
15527
  indexHtml = readFileSync5(indexPath, "utf8");
@@ -15331,10 +15669,10 @@ var isHostLadderProvider = (value) => isLadderProvider(HOST_PREFERENCE_LADDER, v
15331
15669
  var resolveHostLadderOrder = (env, namedVendor) => resolveLadderOrder(HOST_PREFERENCE_LADDER, env.HOSTING_PROVIDER, namedVendor);
15332
15670
 
15333
15671
  // ../packages/deploy/src/liveWork/netlifyProvision.ts
15334
- import { createHash } from "crypto";
15672
+ import { createHash as createHash2 } from "crypto";
15335
15673
  import { mkdirSync as mkdirSync4, readdirSync, readFileSync as readFileSync6, statSync } from "fs";
15336
15674
  import { tmpdir as tmpdir5 } from "os";
15337
- import { join as join23, relative } from "path";
15675
+ import { join as join24, relative as relative2 } from "path";
15338
15676
  import { Effect as Effect16 } from "effect";
15339
15677
  var readNetlifyAuthToken = (env) => {
15340
15678
  const value = env.NETLIFY_AUTH_TOKEN;
@@ -15355,7 +15693,7 @@ var collectStaticFiles = (buildDir) => {
15355
15693
  const out = /* @__PURE__ */ new Map();
15356
15694
  const walk = (dir) => {
15357
15695
  for (const entry of readdirSync(dir)) {
15358
- const full = join23(dir, entry);
15696
+ const full = join24(dir, entry);
15359
15697
  const st = statSync(full);
15360
15698
  if (st.isDirectory()) {
15361
15699
  walk(full);
@@ -15364,7 +15702,7 @@ var collectStaticFiles = (buildDir) => {
15364
15702
  if (!st.isFile()) {
15365
15703
  continue;
15366
15704
  }
15367
- const rel = relative(buildDir, full).split("\\").join("/");
15705
+ const rel = relative2(buildDir, full).split("\\").join("/");
15368
15706
  const webPath = rel.startsWith("/") ? rel : `/${rel}`;
15369
15707
  out.set(webPath, readFileSync6(full));
15370
15708
  }
@@ -15372,7 +15710,7 @@ var collectStaticFiles = (buildDir) => {
15372
15710
  walk(buildDir);
15373
15711
  return out;
15374
15712
  };
15375
- var sha1Hex = (bytes) => createHash("sha1").update(bytes).digest("hex");
15713
+ var sha1Hex = (bytes) => createHash2("sha1").update(bytes).digest("hex");
15376
15714
  var typedNetlifyError = (code, hopClass, message) => Object.assign(new Error(message), { hopClass, code });
15377
15715
  var mapNetlifyHttp = (status, body, code) => {
15378
15716
  const lower = body.toLowerCase();
@@ -15437,7 +15775,7 @@ var createNetlifyHost = (options) => Effect16.gen(function* () {
15437
15775
  );
15438
15776
  }
15439
15777
  if (options.createSite === void 0) {
15440
- const parent = options.cwd ?? join23(tmpdir5(), defaultLiveWorkProjectName("vybekiit-lw-nl-site"));
15778
+ const parent = options.cwd ?? join24(tmpdir5(), defaultLiveWorkProjectName("vybekiit-lw-nl-site"));
15441
15779
  mkdirSync4(parent, { recursive: true });
15442
15780
  buildDir = writeDemoStaticSite(parent);
15443
15781
  }
@@ -15692,7 +16030,7 @@ var buyerHostSuccessMessage = (provider, hopped, fromProvider) => {
15692
16030
  // ../packages/deploy/src/liveWork/railwayHostProvision.ts
15693
16031
  import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "fs";
15694
16032
  import { tmpdir as tmpdir6 } from "os";
15695
- import { join as join24 } from "path";
16033
+ import { join as join25 } from "path";
15696
16034
  import { Effect as Effect17 } from "effect";
15697
16035
  var defaultRailwayHostCliRunner = async (args, options = {}) => {
15698
16036
  const { execFile: execFile8 } = await import("child_process");
@@ -15755,11 +16093,11 @@ var createRailwayHost = (options) => Effect17.gen(function* () {
15755
16093
  })
15756
16094
  );
15757
16095
  }
15758
- workDir = workDir ?? join24(tmpdir6(), defaultLiveWorkProjectName("vybekiit-lw-r-site"));
16096
+ workDir = workDir ?? join25(tmpdir6(), defaultLiveWorkProjectName("vybekiit-lw-r-site"));
15759
16097
  mkdirSync5(workDir, { recursive: true });
15760
16098
  buildDir = writeDemoStaticSite(workDir);
15761
16099
  writeFileSync4(
15762
- join24(workDir, "package.json"),
16100
+ join25(workDir, "package.json"),
15763
16101
  JSON.stringify({
15764
16102
  name: projectName,
15765
16103
  private: true,
@@ -15861,7 +16199,7 @@ var mapRailwayHostCause = (cause) => {
15861
16199
  // ../packages/deploy/src/liveWork/renderProvision.ts
15862
16200
  import { mkdirSync as mkdirSync6 } from "fs";
15863
16201
  import { tmpdir as tmpdir7 } from "os";
15864
- import { join as join25 } from "path";
16202
+ import { join as join26 } from "path";
15865
16203
  import { Effect as Effect18 } from "effect";
15866
16204
  var readRenderApiKey = (env) => {
15867
16205
  const value = env.RENDER_API_KEY;
@@ -15944,7 +16282,7 @@ var createRenderHost = (options) => Effect18.gen(function* () {
15944
16282
  );
15945
16283
  }
15946
16284
  if (options.mode !== "buyer" && (options.buildDir === void 0 || options.buildDir.length === 0)) {
15947
- const parent = options.cwd ?? join25(tmpdir7(), defaultLiveWorkProjectName("vybekiit-lw-rd-site"));
16285
+ const parent = options.cwd ?? join26(tmpdir7(), defaultLiveWorkProjectName("vybekiit-lw-rd-site"));
15948
16286
  mkdirSync6(parent, { recursive: true });
15949
16287
  writeDemoStaticSite(parent);
15950
16288
  }
@@ -16073,7 +16411,7 @@ import { Effect as Effect20 } from "effect";
16073
16411
  // ../packages/deploy/src/liveWork/vercelProvision.ts
16074
16412
  import { mkdirSync as mkdirSync7 } from "fs";
16075
16413
  import { tmpdir as tmpdir8 } from "os";
16076
- import { join as join26 } from "path";
16414
+ import { join as join27 } from "path";
16077
16415
  import { Effect as Effect19 } from "effect";
16078
16416
  var defaultVercelCliRunner = async (args, options = {}) => {
16079
16417
  const { execFile: execFile8 } = await import("child_process");
@@ -16134,7 +16472,7 @@ var createVercelHost = (options) => Effect19.gen(function* () {
16134
16472
  })
16135
16473
  );
16136
16474
  }
16137
- const parent = options.cwd ?? join26(tmpdir8(), defaultLiveWorkProjectName("vybekiit-lw-v-site"));
16475
+ const parent = options.cwd ?? join27(tmpdir8(), defaultLiveWorkProjectName("vybekiit-lw-v-site"));
16138
16476
  mkdirSync7(parent, { recursive: true });
16139
16477
  buildDir = writeDemoStaticSite(parent);
16140
16478
  }
@@ -16521,7 +16859,7 @@ var parseLiveWorkHostFlags = (args) => {
16521
16859
  const cwdRaw = readFlagValue(args, "cwd");
16522
16860
  const buildDirRaw = readFlagValue(args, "build-dir");
16523
16861
  const projectNameRaw = readFlagValue(args, "project-name");
16524
- const cwd = resolve8(process8.cwd(), cwdRaw === void 0 || cwdRaw === "" ? "." : cwdRaw);
16862
+ const cwd = resolve8(process9.cwd(), cwdRaw === void 0 || cwdRaw === "" ? "." : cwdRaw);
16525
16863
  if (!isLiveWorkMode2(modeRaw)) {
16526
16864
  return {
16527
16865
  mode: "buyer",
@@ -16584,7 +16922,7 @@ var runLiveWorkHost = async (args) => {
16584
16922
  exitCode: 1
16585
16923
  };
16586
16924
  }
16587
- const env = mergeEnv(process8.env, loadEnvFile2(flags.cwd));
16925
+ const env = mergeEnv(process9.env, loadEnvFile2(flags.cwd));
16588
16926
  const either = await Effect23.runPromise(
16589
16927
  Effect23.either(
16590
16928
  runHostLiveWork({
@@ -16626,7 +16964,7 @@ var runLiveWorkHost = async (args) => {
16626
16964
 
16627
16965
  // src/commands/liveWorkPaymentsCmd.ts
16628
16966
  import { resolve as resolve9 } from "path";
16629
- import process9 from "process";
16967
+ import process10 from "process";
16630
16968
 
16631
16969
  // ../packages/payments/src/liveWork/journeyEvents.ts
16632
16970
  var toPaymentsLiveWorkJourneyEvents = (result) => {
@@ -16837,7 +17175,7 @@ var parseLiveWorkPaymentsFlags = (args) => {
16837
17175
  const modeRaw = readFlagValue(args, "mode") ?? "buyer";
16838
17176
  const vendorRaw = readFlagValue(args, "vendor");
16839
17177
  const cwdRaw = readFlagValue(args, "cwd");
16840
- const cwd = resolve9(process9.cwd(), cwdRaw === void 0 || cwdRaw === "" ? "." : cwdRaw);
17178
+ const cwd = resolve9(process10.cwd(), cwdRaw === void 0 || cwdRaw === "" ? "." : cwdRaw);
16841
17179
  if (!isLiveWorkMode3(modeRaw)) {
16842
17180
  return {
16843
17181
  mode: "buyer",
@@ -16895,7 +17233,7 @@ var runLiveWorkPayments = async (args) => {
16895
17233
  exitCode: 1
16896
17234
  };
16897
17235
  }
16898
- const env = mergeEnv(process9.env, loadEnvFile2(flags.cwd));
17236
+ const env = mergeEnv(process10.env, loadEnvFile2(flags.cwd));
16899
17237
  const either = await Effect26.runPromise(
16900
17238
  Effect26.either(
16901
17239
  runPaymentsLiveWork({
@@ -16937,7 +17275,7 @@ var runLiveWorkPayments = async (args) => {
16937
17275
  // src/commands/localDev.ts
16938
17276
  import { spawn } from "child_process";
16939
17277
  import { access as access9 } from "fs/promises";
16940
- import { dirname as dirname9, join as join27 } from "path";
17278
+ import { dirname as dirname9, join as join28 } from "path";
16941
17279
  import { fileURLToPath as fileURLToPath6 } from "url";
16942
17280
 
16943
17281
  // src/lib/agentDetection.ts
@@ -17062,15 +17400,15 @@ var listAgents = () => Object.values(AGENTS);
17062
17400
  // src/commands/localDev.ts
17063
17401
  var HERE6 = dirname9(fileURLToPath6(import.meta.url));
17064
17402
  var PORT = 3005;
17065
- var resolveMonorepoRoot = () => join27(HERE6, "..", "..", "..");
17403
+ var resolveMonorepoRoot = () => join28(HERE6, "..", "..", "..");
17066
17404
  var openBrowser = async (url) => {
17067
- const { default: open } = await import("open");
17068
- await open(url);
17405
+ const { default: open2 } = await import("open");
17406
+ await open2(url);
17069
17407
  };
17070
17408
  var runLocalDev = async () => {
17071
17409
  const root = resolveMonorepoRoot();
17072
17410
  try {
17073
- await access9(join27(root, "pnpm-workspace.yaml"));
17411
+ await access9(join28(root, "pnpm-workspace.yaml"));
17074
17412
  } catch {
17075
17413
  process.stderr.write("\u274C vybekiit local-dev must be run from inside the VybeKiit monorepo.\n");
17076
17414
  return 1;
@@ -17084,7 +17422,7 @@ var runLocalDev = async () => {
17084
17422
  process.stdout.write(` URL: http://localhost:${PORT}
17085
17423
  `);
17086
17424
  process.stdout.write("\n");
17087
- const appDir = join27(root, "apps", "localDevelopmentWebsite");
17425
+ const appDir = join28(root, "apps", "localDevelopmentWebsite");
17088
17426
  const child = spawn("pnpm", ["dev"], {
17089
17427
  cwd: appDir,
17090
17428
  stdio: "pipe",
@@ -17118,10 +17456,10 @@ var runLocalDev = async () => {
17118
17456
  };
17119
17457
 
17120
17458
  // src/commands/new.ts
17121
- import process10 from "process";
17459
+ import process11 from "process";
17122
17460
  var runNew = async (args) => {
17123
17461
  const [template, dir] = args;
17124
- process10.stderr.write(
17462
+ process11.stderr.write(
17125
17463
  `Note: \`vybekiit new\` is deprecated. Use \`vybekiit create app ${CREATE_SURFACE_PIPE_FLAGS}\`.
17126
17464
  `
17127
17465
  );
@@ -17132,24 +17470,24 @@ var runNew = async (args) => {
17132
17470
  if (template === void 0 || template === "") {
17133
17471
  return await runCreateApp([]);
17134
17472
  }
17135
- process10.stderr.write(
17473
+ process11.stderr.write(
17136
17474
  `Unknown surface "${template}". Use ${CREATE_SURFACE_LIST_FLAGS} (spa is not a create-app surface).
17137
17475
  `
17138
17476
  );
17139
- process10.stderr.write(
17477
+ process11.stderr.write(
17140
17478
  "Examples:\n vybekiit create app --web my-app\n vybekiit create app --mobile\n"
17141
17479
  );
17142
17480
  return 1;
17143
17481
  };
17144
17482
 
17145
17483
  // src/commands/piecesCmd.ts
17146
- import process11 from "process";
17484
+ import process12 from "process";
17147
17485
 
17148
17486
  // src/lib/pageRecipeCatalog.ts
17149
- import { readFile as readFile11 } from "fs/promises";
17150
- import { join as join28 } from "path";
17151
- var PAGE_RECIPE_MANIFEST_RELATIVE = join28("scripts", "data", "page-recipe-manifest.json");
17152
- var pageRecipeManifestPath = (kitRoot) => join28(kitRoot, PAGE_RECIPE_MANIFEST_RELATIVE);
17487
+ import { readFile as readFile12 } from "fs/promises";
17488
+ import { join as join29 } from "path";
17489
+ var PAGE_RECIPE_MANIFEST_RELATIVE = join29("scripts", "data", "page-recipe-manifest.json");
17490
+ var pageRecipeManifestPath = (kitRoot) => join29(kitRoot, PAGE_RECIPE_MANIFEST_RELATIVE);
17153
17491
  var nonEmptyOr = (value, fallback) => {
17154
17492
  if (value === void 0 || value === "") {
17155
17493
  return fallback;
@@ -17228,7 +17566,7 @@ var parsePageRecipeManifest = (raw) => {
17228
17566
  };
17229
17567
  var loadPageRecipes = async (kitRoot) => {
17230
17568
  try {
17231
- const raw = await readFile11(pageRecipeManifestPath(kitRoot), "utf8");
17569
+ const raw = await readFile12(pageRecipeManifestPath(kitRoot), "utf8");
17232
17570
  return parsePageRecipeManifest(raw);
17233
17571
  } catch {
17234
17572
  return [];
@@ -17237,8 +17575,8 @@ var loadPageRecipes = async (kitRoot) => {
17237
17575
  var findPageRecipe = (recipes, idOrSlug) => recipes.find((recipe) => recipe.id === idOrSlug || recipe.slug === idOrSlug);
17238
17576
 
17239
17577
  // src/lib/pageRecipeInstall.ts
17240
- import { access as access11, mkdir as mkdir7, readFile as readFile13, writeFile as writeFile8 } from "fs/promises";
17241
- import { basename as basename2, dirname as dirname11, join as join31, relative as relative3, resolve as resolve11 } from "path";
17578
+ import { access as access11, mkdir as mkdir8, readFile as readFile14, writeFile as writeFile9 } from "fs/promises";
17579
+ import { basename as basename2, dirname as dirname11, join as join32, relative as relative4, resolve as resolve11 } from "path";
17242
17580
 
17243
17581
  // src/lib/pageRecipeImports.ts
17244
17582
  var SHARED_IMPORT_PATTERN = /from\s+['"]((?:\.\.\/)+shared\/[^'"]+|\.\/shared\/[^'"]+)['"]/g;
@@ -17303,8 +17641,8 @@ var rewriteInstalledSource = (source) => (
17303
17641
  );
17304
17642
 
17305
17643
  // src/lib/pageRecipePlanFiles.ts
17306
- import { access as access10, readFile as readFile12 } from "fs/promises";
17307
- import { basename, dirname as dirname10, join as join30, relative as relative2 } from "path";
17644
+ import { access as access10, readFile as readFile13 } from "fs/promises";
17645
+ import { basename, dirname as dirname10, join as join31, relative as relative3 } from "path";
17308
17646
 
17309
17647
  // src/lib/pageRecipeRouteStub.ts
17310
17648
  var buildRouteStub = (exportName, componentImportPath, targetRoute) => `import { ${exportName} } from '${componentImportPath}';
@@ -17406,7 +17744,7 @@ export const foregroundTripletFor = (hex: string): string => {
17406
17744
  `;
17407
17745
 
17408
17746
  // src/lib/resolveAppSurface.ts
17409
- import { join as join29, resolve as resolve10 } from "path";
17747
+ import { join as join30, resolve as resolve10 } from "path";
17410
17748
  var stripLeadingSlashes = (route) => {
17411
17749
  let result = route;
17412
17750
  while (result.startsWith("/")) {
@@ -17425,11 +17763,11 @@ var appRootCandidates = (dest) => {
17425
17763
  const root = resolve10(dest);
17426
17764
  return [
17427
17765
  root,
17428
- join29(root, "templates", "web"),
17429
- join29(root, "web"),
17430
- join29(root, "templates", "spa"),
17431
- join29(root, "spa"),
17432
- join29(root, "apps", "web")
17766
+ join30(root, "templates", "web"),
17767
+ join30(root, "web"),
17768
+ join30(root, "templates", "spa"),
17769
+ join30(root, "spa"),
17770
+ join30(root, "apps", "web")
17433
17771
  ];
17434
17772
  };
17435
17773
  var fallbackLayout = (dest) => {
@@ -17438,15 +17776,15 @@ var fallbackLayout = (dest) => {
17438
17776
  appRoot: root,
17439
17777
  appDir: void 0,
17440
17778
  usesLocaleSegment: false,
17441
- componentsDir: join29(root, "src", "components", "pageRecipes")
17779
+ componentsDir: join30(root, "src", "components", "pageRecipes")
17442
17780
  };
17443
17781
  };
17444
17782
  var probeAppRoot = async (candidate) => {
17445
- const appAtRoot = join29(candidate, "app");
17446
- const appUnderSrc = join29(candidate, "src", "app");
17447
- const srcDir = join29(candidate, "src");
17783
+ const appAtRoot = join30(candidate, "app");
17784
+ const appUnderSrc = join30(candidate, "src", "app");
17785
+ const srcDir = join30(candidate, "src");
17448
17786
  const [hasPackage, hasAppAtRoot, hasAppUnderSrc, hasSrc] = await Promise.all([
17449
- pathExists3(join29(candidate, "package.json")),
17787
+ pathExists3(join30(candidate, "package.json")),
17450
17788
  pathExists3(appAtRoot),
17451
17789
  pathExists3(appUnderSrc),
17452
17790
  pathExists3(srcDir)
@@ -17460,8 +17798,8 @@ var probeAppRoot = async (candidate) => {
17460
17798
  } else if (hasAppUnderSrc) {
17461
17799
  appDir = appUnderSrc;
17462
17800
  }
17463
- const usesLocaleSegment = appDir !== void 0 && await pathExists3(join29(appDir, "[locale]"));
17464
- const componentsDir = hasSrc ? join29(candidate, "src", "components", "pageRecipes") : join29(candidate, "components", "pageRecipes");
17801
+ const usesLocaleSegment = appDir !== void 0 && await pathExists3(join30(appDir, "[locale]"));
17802
+ const componentsDir = hasSrc ? join30(candidate, "src", "components", "pageRecipes") : join30(candidate, "components", "pageRecipes");
17465
17803
  return {
17466
17804
  appRoot: candidate,
17467
17805
  appDir,
@@ -17481,7 +17819,7 @@ var routeSegmentPath = (targetRoute, usesLocaleSegment) => {
17481
17819
  const trimmed = stripTrailingSlashes(stripLeadingSlashes(targetRoute));
17482
17820
  const body = trimmed === "" ? "index" : trimmed;
17483
17821
  if (usesLocaleSegment) {
17484
- return join29("[locale]", body);
17822
+ return join30("[locale]", body);
17485
17823
  }
17486
17824
  return body;
17487
17825
  };
@@ -17518,7 +17856,7 @@ var resolveSourceFile = async (basePath) => {
17518
17856
  var findKitSharedDir = async (fromFile) => {
17519
17857
  let dir = dirname10(fromFile);
17520
17858
  for (let depth = 0; depth < 6; depth += 1) {
17521
- const candidate = join30(dir, "shared");
17859
+ const candidate = join31(dir, "shared");
17522
17860
  if (await pathExists5(candidate)) {
17523
17861
  return candidate;
17524
17862
  }
@@ -17532,19 +17870,19 @@ var findKitSharedDir = async (fromFile) => {
17532
17870
  };
17533
17871
  var loadSharedModule = async (options) => {
17534
17872
  const { spec, appRoot, componentsDir, kitSharedDir } = options;
17535
- const kitSharedBase = join30(kitSharedDir, stripLeadingDotSlash(spec));
17873
+ const kitSharedBase = join31(kitSharedDir, stripLeadingDotSlash(spec));
17536
17874
  const kitSharedFile = await resolveSourceFile(kitSharedBase);
17537
17875
  if (kitSharedFile === null) {
17538
17876
  throw new Error(`Missing shared recipe dependency: ${spec}`);
17539
17877
  }
17540
- const sharedDest = join30(componentsDir, "shared", basename(kitSharedFile));
17541
- const sharedRaw = await readFile12(kitSharedFile, "utf8");
17878
+ const sharedDest = join31(componentsDir, "shared", basename(kitSharedFile));
17879
+ const sharedRaw = await readFile13(kitSharedFile, "utf8");
17542
17880
  const sharedContent = rewriteInstalledSource(sharedRaw);
17543
17881
  const nextSpecs = collectRelativeImports(sharedRaw).map((rel) => stripLeadingDotSlash(rel));
17544
17882
  return {
17545
17883
  file: {
17546
17884
  absolutePath: sharedDest,
17547
- relativePath: relative2(appRoot, sharedDest),
17885
+ relativePath: relative3(appRoot, sharedDest),
17548
17886
  kind: "shared",
17549
17887
  content: sharedContent
17550
17888
  },
@@ -17617,7 +17955,7 @@ var planRouteFile = async (options) => {
17617
17955
  return [];
17618
17956
  }
17619
17957
  const segment = routeSegmentPath(recipe.targetRoute, usesLocaleSegment);
17620
- const routeFile = join30(appDir, segment, "page.tsx");
17958
+ const routeFile = join31(appDir, segment, "page.tsx");
17621
17959
  const importPath = `@/components/pageRecipes/${stripComponentExtension(recipeFileName)}`;
17622
17960
  if (await pathExists5(routeFile)) {
17623
17961
  return [];
@@ -17625,7 +17963,7 @@ var planRouteFile = async (options) => {
17625
17963
  return [
17626
17964
  {
17627
17965
  absolutePath: routeFile,
17628
- relativePath: relative2(appRoot, routeFile),
17966
+ relativePath: relative3(appRoot, routeFile),
17629
17967
  kind: "route",
17630
17968
  content: buildRouteStub(recipe.exportName, importPath, recipe.targetRoute)
17631
17969
  }
@@ -17635,11 +17973,11 @@ var themeHelperFiles = (layout, needsThemeHelper) => {
17635
17973
  if (!needsThemeHelper) {
17636
17974
  return [];
17637
17975
  }
17638
- const helperDest = join30(layout.componentsDir, "shared", "themeHelpers.ts");
17976
+ const helperDest = join31(layout.componentsDir, "shared", "themeHelpers.ts");
17639
17977
  return [
17640
17978
  {
17641
17979
  absolutePath: helperDest,
17642
- relativePath: relative2(layout.appRoot, helperDest),
17980
+ relativePath: relative3(layout.appRoot, helperDest),
17643
17981
  kind: "theme-helper",
17644
17982
  content: THEME_HELPER_SOURCE
17645
17983
  }
@@ -17672,15 +18010,15 @@ var pathExists6 = async (path) => {
17672
18010
  var planPageRecipeInstall = async (options) => {
17673
18011
  const { kitRoot, dest, recipe } = options;
17674
18012
  const layout = await resolveAppSurface(dest);
17675
- const sourceAbs = join31(kitRoot, recipe.sourcePath);
18013
+ const sourceAbs = join32(kitRoot, recipe.sourcePath);
17676
18014
  if (!await pathExists6(sourceAbs)) {
17677
18015
  throw new Error(
17678
18016
  `Recipe source not found at ${recipe.sourcePath}. Re-run from a kit workspace or with kit access.`
17679
18017
  );
17680
18018
  }
17681
- const recipeSource = await readFile13(sourceAbs, "utf8");
18019
+ const recipeSource = await readFile14(sourceAbs, "utf8");
17682
18020
  const recipeFileName = basename2(recipe.sourcePath);
17683
- const recipeDest = join31(layout.componentsDir, recipeFileName);
18021
+ const recipeDest = join32(layout.componentsDir, recipeFileName);
17684
18022
  const shared = await planSharedFiles({
17685
18023
  sourceAbs,
17686
18024
  recipeSource,
@@ -17697,7 +18035,7 @@ var planPageRecipeInstall = async (options) => {
17697
18035
  const followUps = buildInstallFollowUps(recipe);
17698
18036
  const mainFile = {
17699
18037
  absolutePath: recipeDest,
17700
- relativePath: relative3(layout.appRoot, recipeDest),
18038
+ relativePath: relative4(layout.appRoot, recipeDest),
17701
18039
  kind: "component",
17702
18040
  content: rewriteInstalledSource(recipeSource)
17703
18041
  };
@@ -17728,8 +18066,8 @@ var applyPageRecipeInstall = async (plan, options = { force: false }) => {
17728
18066
  if (exists3 && !options.force) {
17729
18067
  return { kind: "skipped", path: file.relativePath };
17730
18068
  }
17731
- await mkdir7(dirname11(file.absolutePath), { recursive: true });
17732
- await writeFile8(file.absolutePath, file.content, "utf8");
18069
+ await mkdir8(dirname11(file.absolutePath), { recursive: true });
18070
+ await writeFile9(file.absolutePath, file.content, "utf8");
17733
18071
  return { kind: "written", path: file.relativePath };
17734
18072
  })
17735
18073
  );
@@ -17776,6 +18114,15 @@ var backendPieces = () => [
17776
18114
  command: "vybekiit backend add-upload"
17777
18115
  }
17778
18116
  ];
18117
+ var reportModePieces = () => [
18118
+ {
18119
+ kind: "report-mode",
18120
+ id: "report-mode",
18121
+ title: "Report Mode",
18122
+ summary: "Install the dev-only point & fix inspect/report overlay into an existing app.",
18123
+ command: "vybekiit add report-mode [--to=dir]"
18124
+ }
18125
+ ];
17779
18126
  var dbPieces = () => ALL_PRESETS.map((preset) => {
17780
18127
  const summary = preset.description === void 0 || preset.description === "" ? `Database preset ${preset.id}` : preset.description;
17781
18128
  return {
@@ -17795,7 +18142,7 @@ var pageRecipePieces = (recipes) => recipes.map((recipe) => ({
17795
18142
  linkedPresets: recipe.presetIds,
17796
18143
  command: `vybekiit add page-recipe ${recipe.id}`
17797
18144
  }));
17798
- var buildCatalog = (recipes, kindFilter) => [...dbPieces(), ...pageRecipePieces(recipes), ...backendPieces()].filter(
18145
+ var buildCatalog = (recipes, kindFilter) => [...dbPieces(), ...pageRecipePieces(recipes), ...backendPieces(), ...reportModePieces()].filter(
17799
18146
  (piece) => kindFilter === void 0 || piece.kind === kindFilter
17800
18147
  );
17801
18148
 
@@ -17931,7 +18278,7 @@ var runAddPageRecipe = async (args) => {
17931
18278
  if (recipe === void 0) {
17932
18279
  return recipeError(`Unknown page recipe "${recipeId}". Run: vybekiit list-page-recipes`);
17933
18280
  }
17934
- const dest = resolveInstallDest(destArg, process11.cwd());
18281
+ const dest = resolveInstallDest(destArg, process12.cwd());
17935
18282
  const plan = await planPageRecipeInstall({ kitRoot, dest, recipe });
17936
18283
  if (flags.dryRun) {
17937
18284
  return {
@@ -17955,12 +18302,12 @@ var runAddPageRecipe = async (args) => {
17955
18302
  };
17956
18303
 
17957
18304
  // src/commands/piecesInteractive.ts
17958
- import process13 from "process";
17959
- import { cancel, isCancel, select } from "@clack/prompts";
18305
+ import process15 from "process";
18306
+ import { cancel, isCancel as isCancel2, select } from "@clack/prompts";
17960
18307
 
17961
18308
  // src/commands/presetsCmd.ts
17962
18309
  import { resolve as resolve12 } from "path";
17963
- import process12 from "process";
18310
+ import process13 from "process";
17964
18311
  import { Effect as Effect27, Either as Either5 } from "effect";
17965
18312
  var POSTGRES_PROVIDERS = ["supabase", "neon", "railway"];
17966
18313
  var NOSQL_PROVIDERS = ["mongodb", "firebase", "aws"];
@@ -17988,10 +18335,10 @@ var parseFlags = (args) => {
17988
18335
  };
17989
18336
  var resolvePresetEnv = (cwd) => {
17990
18337
  if (cwd === void 0 || cwd === "") {
17991
- return process12.env;
18338
+ return process13.env;
17992
18339
  }
17993
- const absolute = resolve12(process12.cwd(), cwd);
17994
- return mergeEnv(process12.env, loadEnvFile2(absolute));
18340
+ const absolute = resolve12(process13.cwd(), cwd);
18341
+ return mergeEnv(process13.env, loadEnvFile2(absolute));
17995
18342
  };
17996
18343
  var databaseUrlFromEnv = (env) => env.DATABASE_URL;
17997
18344
  var isNosqlProvider2 = (provider) => provider === "mongodb" || provider === "firebase" || provider === "aws";
@@ -18095,7 +18442,7 @@ var runApplyPreset = async (args) => {
18095
18442
  result.ok ? {
18096
18443
  ok: true,
18097
18444
  ...result.value,
18098
- ...flags.cwd === void 0 ? {} : { cwd: resolve12(process12.cwd(), flags.cwd) }
18445
+ ...flags.cwd === void 0 ? {} : { cwd: resolve12(process13.cwd(), flags.cwd) }
18099
18446
  } : result,
18100
18447
  null,
18101
18448
  2
@@ -18155,97 +18502,591 @@ var runListPresets = () => {
18155
18502
  };
18156
18503
  };
18157
18504
 
18158
- // src/commands/piecesInteractive.ts
18159
- var runListPath = async () => {
18160
- const result = await runListPieces([]);
18161
- process13.stdout.write(`${result.json}
18162
- `);
18163
- return result.exitCode;
18164
- };
18165
- var runDbPresetPath = async () => {
18166
- const picked = await select({
18167
- message: "Which database preset?",
18168
- options: ALL_PRESETS.map((preset) => ({
18169
- value: preset.id,
18170
- label: preset.id,
18171
- hint: preset.description === void 0 || preset.description === "" ? preset.id : preset.description
18172
- }))
18173
- });
18174
- if (isCancel(picked) || typeof picked !== "string") {
18175
- cancel("Cancelled.");
18176
- return 1;
18505
+ // src/commands/reportModeCmd.ts
18506
+ import { spawnSync } from "child_process";
18507
+ import process14 from "process";
18508
+
18509
+ // ../packages/reportMode/src/deeplink.ts
18510
+ var inferVybeAssistant = (options) => {
18511
+ if (options.cursorSession) {
18512
+ return "cursor";
18177
18513
  }
18178
- const result = await runApplyPreset([picked, "--dry-run"]);
18179
- process13.stdout.write(`${result.json}
18180
- `);
18181
- process13.stdout.write(
18182
- `
18183
- Dry-run shown. Apply for real with: vybekiit apply-preset ${picked}
18184
- (Needs DATABASE_URL in the project.)
18185
- `
18186
- );
18187
- return result.exitCode;
18514
+ if (options.claudeInstalled) {
18515
+ return "claude";
18516
+ }
18517
+ if (options.codexInstalled) {
18518
+ return "codex";
18519
+ }
18520
+ if (options.kiroInstalled === true) {
18521
+ return "kiro";
18522
+ }
18523
+ if (options.kimiInstalled === true) {
18524
+ return "kimi";
18525
+ }
18526
+ if (options.grokInstalled === true) {
18527
+ return "grok";
18528
+ }
18529
+ if (options.devinInstalled === true) {
18530
+ return "devin";
18531
+ }
18532
+ return null;
18188
18533
  };
18189
- var runPageRecipePath = async () => {
18190
- let cleanup;
18534
+
18535
+ // src/lib/reportModeInstall.ts
18536
+ import { access as access12, mkdir as mkdir9, readdir as readdir8, readFile as readFile16, writeFile as writeFile11 } from "fs/promises";
18537
+ import { dirname as dirname12, join as join33, relative as relative5 } from "path";
18538
+
18539
+ // src/lib/packageJsonDeps.ts
18540
+ import { readFile as readFile15, writeFile as writeFile10 } from "fs/promises";
18541
+ var ensureDependencies = async (pkgPath, deps) => {
18542
+ let raw;
18191
18543
  try {
18192
- const resolved = await resolveKitSource();
18193
- const { cleanup: resolvedCleanup, kitRoot } = resolved;
18194
- cleanup = resolvedCleanup;
18195
- const recipes = await loadPageRecipes(kitRoot);
18196
- if (recipes.length === 0) {
18197
- process13.stderr.write("No page recipes available from the kit source.\n");
18198
- return 1;
18199
- }
18200
- const picked = await select({
18201
- message: "Which page recipe?",
18202
- options: recipes.map((recipe) => ({
18203
- value: recipe.id,
18204
- label: recipe.title,
18205
- hint: `${recipe.groupLabel} \xB7 ${recipe.targetRoute}`
18206
- }))
18207
- });
18208
- if (isCancel(picked) || typeof picked !== "string") {
18209
- cancel("Cancelled.");
18210
- return 1;
18544
+ raw = await readFile15(pkgPath, "utf8");
18545
+ } catch {
18546
+ return [];
18547
+ }
18548
+ const pkg = JSON.parse(raw);
18549
+ const dependencies = pkg.dependencies ?? {};
18550
+ const added = [];
18551
+ for (const [name, version] of Object.entries(deps)) {
18552
+ if (dependencies[name] === void 0) {
18553
+ dependencies[name] = version;
18554
+ added.push(name);
18211
18555
  }
18212
- const result = await runAddPageRecipe([picked, "--to=."]);
18213
- process13.stdout.write(`${result.json}
18556
+ }
18557
+ if (added.length === 0) {
18558
+ return [];
18559
+ }
18560
+ pkg.dependencies = dependencies;
18561
+ await writeFile10(pkgPath, `${JSON.stringify(pkg, null, 2)}
18214
18562
  `);
18215
- if (result.exitCode === 0) {
18216
- process13.stdout.write(
18217
- `
18218
- Installed "${picked}" into the current folder. Wire the TODOs in the JSON report next.
18219
- `
18220
- );
18563
+ return added;
18564
+ };
18565
+
18566
+ // src/lib/reportModeInstall.ts
18567
+ var INSTALLABLE_SURFACES = ["web", "mobile", "extension"];
18568
+ var isInstallableSurface = (surface) => INSTALLABLE_SURFACES.includes(surface);
18569
+ var listFilesRecursive = async (dir, prefix = "") => {
18570
+ try {
18571
+ const entries = await readdir8(dir, { withFileTypes: true });
18572
+ const nested = await Promise.all(
18573
+ entries.map(async (entry) => {
18574
+ const rel = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
18575
+ if (entry.isDirectory()) {
18576
+ return await listFilesRecursive(join33(dir, entry.name), rel);
18577
+ }
18578
+ return [rel];
18579
+ })
18580
+ );
18581
+ return nested.flat();
18582
+ } catch {
18583
+ return [];
18584
+ }
18585
+ };
18586
+ var defaultReportModeFs = {
18587
+ listFiles: (dir) => listFilesRecursive(dir),
18588
+ readText: async (path) => {
18589
+ try {
18590
+ return await readFile16(path, "utf8");
18591
+ } catch {
18592
+ return null;
18221
18593
  }
18222
- return result.exitCode;
18223
- } catch (error) {
18224
- const message = caughtMessage(error);
18225
- process13.stderr.write(`${message}
18226
- `);
18227
- return 1;
18228
- } finally {
18229
- if (cleanup !== void 0) {
18230
- await cleanup();
18594
+ },
18595
+ exists: async (path) => {
18596
+ try {
18597
+ await access12(path);
18598
+ return true;
18599
+ } catch {
18600
+ return false;
18231
18601
  }
18602
+ },
18603
+ writeText: async (path, content) => {
18604
+ await mkdir9(dirname12(path), { recursive: true });
18605
+ await writeFile11(path, content, "utf8");
18232
18606
  }
18233
18607
  };
18234
- var runAddPiecesInteractive = async () => {
18235
- if (!isInteractive()) {
18236
- process13.stderr.write(
18237
- "add requires arguments in non-interactive mode. Try: vybekiit list-pieces\n"
18238
- );
18239
- return 1;
18608
+ var SURFACE_SOURCES = {
18609
+ web: {
18610
+ subtrees: ["src/components/report-mode", "src/lib/report-mode", "src/components/walkthrough"],
18611
+ companions: ["src/lib/nodeEnv.ts", "src/lib/utils.ts"],
18612
+ assumedPresent: []
18613
+ },
18614
+ mobile: {
18615
+ subtrees: ["src/components/report-mode", "src/lib/report-mode"],
18616
+ companions: ["src/lib/nodeEnv.ts"],
18617
+ assumedPresent: ["@/theme/useTheme"]
18618
+ },
18619
+ extension: {
18620
+ subtrees: ["src/components/report-mode", "src/lib/report-mode"],
18621
+ companions: ["src/lib/utils.ts", "styles/report-mode-note.css"],
18622
+ assumedPresent: ["@/components/ui/button", "@/components/ui/input"]
18240
18623
  }
18241
- const kind = await select({
18242
- message: "What kind of ready piece?",
18243
- options: [
18244
- {
18245
- value: "page-recipe",
18624
+ };
18625
+ var REWRITE_TARGET = "src/components/report-mode/report-mode-dev.tsx";
18626
+ var UTILS_FILE = "src/lib/utils.ts";
18627
+ var WORKSPACE_RANGE = "workspace:*";
18628
+ var parseDependencies = (raw) => {
18629
+ if (raw === null || raw === "") {
18630
+ return {};
18631
+ }
18632
+ try {
18633
+ const parsed = JSON.parse(raw);
18634
+ return parsed.dependencies ?? {};
18635
+ } catch {
18636
+ return {};
18637
+ }
18638
+ };
18639
+ var rewriteContent = (relativePath, raw, applyRewrite) => {
18640
+ if (!applyRewrite || relativePath !== REWRITE_TARGET) {
18641
+ return raw;
18642
+ }
18643
+ return raw.replaceAll("from '@/i18n/navigation'", "from 'next/navigation'");
18644
+ };
18645
+ var toPlannedFile = async (options) => {
18646
+ const { fs, sourceDir, dest, relativePath, applyRewrite } = options;
18647
+ const raw = await fs.readText(join33(sourceDir, relativePath));
18648
+ if (raw === null) {
18649
+ return null;
18650
+ }
18651
+ const absolutePath = join33(dest, relativePath);
18652
+ return {
18653
+ relativePath,
18654
+ absolutePath,
18655
+ content: rewriteContent(relativePath, raw, applyRewrite),
18656
+ exists: await fs.exists(absolutePath)
18657
+ };
18658
+ };
18659
+ var buildPlannedFiles = async (options) => {
18660
+ const { fs, sourceDir, dest, sources, applyRewrite } = options;
18661
+ const subtreeGroups = await Promise.all(
18662
+ sources.subtrees.map(async (subtree) => {
18663
+ const names = await fs.listFiles(join33(sourceDir, subtree));
18664
+ return names.map((name) => `${subtree}/${name}`);
18665
+ })
18666
+ );
18667
+ const relativePaths = [...subtreeGroups.flat(), ...sources.companions];
18668
+ const planned = await Promise.all(
18669
+ relativePaths.map(
18670
+ (relativePath) => toPlannedFile({ fs, sourceDir, dest, relativePath, applyRewrite })
18671
+ )
18672
+ );
18673
+ return planned.filter((file) => file !== null);
18674
+ };
18675
+ var buildDeps = (surface, sourceDeps, willWriteUtils) => {
18676
+ const deps = { "@vybekiit/report-mode": WORKSPACE_RANGE };
18677
+ if (surface === "web") {
18678
+ deps["@vybekiit/ui"] = WORKSPACE_RANGE;
18679
+ deps["@vybekiit/walkthrough"] = WORKSPACE_RANGE;
18680
+ const { sonner } = sourceDeps;
18681
+ if (sonner !== void 0) {
18682
+ deps.sonner = sonner;
18683
+ }
18684
+ }
18685
+ if (willWriteUtils && (surface === "web" || surface === "extension")) {
18686
+ const { cnfast } = sourceDeps;
18687
+ if (cnfast !== void 0) {
18688
+ deps.cnfast = cnfast;
18689
+ }
18690
+ }
18691
+ return deps;
18692
+ };
18693
+ var buildEnv = (surface, assistant) => {
18694
+ const env = { VYBE_REPORT_MODE: "1" };
18695
+ if (assistant === null) {
18696
+ return env;
18697
+ }
18698
+ const projectSurface = {
18699
+ template: surface,
18700
+ mobile: surface === "mobile",
18701
+ extension: surface === "extension"
18702
+ };
18703
+ return { ...env, ...reportModeEnvKeysForSurface(projectSurface, assistant) };
18704
+ };
18705
+ var planRewrite = async (options) => {
18706
+ const { surface, dest, fs, appSurface, destDeps } = options;
18707
+ if (surface !== "web") {
18708
+ return { applied: false, reason: `No i18n rewrite for the ${surface} surface.` };
18709
+ }
18710
+ const usesLocaleSegment = appSurface?.usesLocaleSegment === true;
18711
+ const hasI18nNavigation = await fs.exists(join33(dest, "src", "i18n", "navigation.ts"));
18712
+ const hasNextIntlDep = destDeps["next-intl"] !== void 0;
18713
+ if (usesLocaleSegment || hasI18nNavigation || hasNextIntlDep) {
18714
+ return { applied: false, reason: "Project uses next-intl; kept @/i18n/navigation." };
18715
+ }
18716
+ return { applied: true, reason: "Non-next-intl project; rewrote to next/navigation." };
18717
+ };
18718
+ var uniquePaths = (paths) => [...new Set(paths)];
18719
+ var buildMountSpec = (surface, dest, appSurface) => {
18720
+ if (surface === "web") {
18721
+ const appDir = appSurface?.appDir;
18722
+ const candidates = [];
18723
+ if (appDir !== void 0 && appSurface?.usesLocaleSegment === true) {
18724
+ candidates.push(join33(appDir, "[locale]", "layout.tsx"));
18725
+ }
18726
+ if (appDir !== void 0) {
18727
+ candidates.push(join33(appDir, "layout.tsx"));
18728
+ }
18729
+ candidates.push(join33(dest, "src", "app", "layout.tsx"));
18730
+ return {
18731
+ component: "ReportModeDevShell",
18732
+ importStatement: "import { ReportModeDevShell } from '@/components/report-mode/report-mode-shell';",
18733
+ jsxTag: "<ReportModeDevShell />",
18734
+ candidatePaths: uniquePaths(candidates),
18735
+ anchor: "</body>"
18736
+ };
18737
+ }
18738
+ if (surface === "mobile") {
18739
+ return {
18740
+ component: "ReportModeDev",
18741
+ importStatement: "import { ReportModeDev } from '@/components/report-mode/report-mode-dev';",
18742
+ jsxTag: "<ReportModeDev />",
18743
+ candidatePaths: [join33(dest, "app", "_layout.tsx")],
18744
+ anchor: void 0
18745
+ };
18746
+ }
18747
+ return {
18748
+ component: "ReportModeDev",
18749
+ importStatement: "import { ReportModeDev } from '@/components/report-mode/report-mode-dev';",
18750
+ jsxTag: "<ReportModeDev />",
18751
+ candidatePaths: [join33(dest, "src", "components", "app-root.tsx")],
18752
+ anchor: void 0
18753
+ };
18754
+ };
18755
+ var insertMount = (content, importStatement, jsxTag, anchor) => {
18756
+ const lines = content.split("\n");
18757
+ const lastImportIndex = lines.reduce(
18758
+ (acc, line, index) => line.startsWith("import ") ? index : acc,
18759
+ -1
18760
+ );
18761
+ const withImport = lastImportIndex >= 0 ? [
18762
+ ...lines.slice(0, lastImportIndex + 1),
18763
+ importStatement,
18764
+ ...lines.slice(lastImportIndex + 1)
18765
+ ].join("\n") : `${importStatement}
18766
+ ${content}`;
18767
+ return withImport.replace(anchor, ` ${jsxTag}
18768
+ ${anchor}`);
18769
+ };
18770
+ var planMount = async (fs, spec) => {
18771
+ const loaded = await Promise.all(
18772
+ spec.candidatePaths.map(async (candidate) => ({
18773
+ candidate,
18774
+ content: await fs.readText(candidate)
18775
+ }))
18776
+ );
18777
+ const existing = loaded.filter(
18778
+ (entry) => entry.content !== null
18779
+ );
18780
+ const base = {
18781
+ path: existing[0]?.candidate ?? spec.candidatePaths[0] ?? "",
18782
+ importSnippet: spec.importStatement,
18783
+ jsxSnippet: spec.jsxTag
18784
+ };
18785
+ if (existing.length === 0) {
18786
+ return { ...base, status: "todo", reason: "No root layout found; mount manually." };
18787
+ }
18788
+ const alreadyMounted = existing.find((entry) => entry.content.includes(spec.component));
18789
+ if (alreadyMounted !== void 0) {
18790
+ return {
18791
+ ...base,
18792
+ path: alreadyMounted.candidate,
18793
+ status: "already",
18794
+ reason: "Report Mode is already mounted."
18795
+ };
18796
+ }
18797
+ const anchor = spec.anchor;
18798
+ if (anchor !== void 0) {
18799
+ const mountable = existing.filter((entry) => entry.content.split(anchor).length - 1 === 1);
18800
+ const target = mountable[0];
18801
+ if (mountable.length === 1 && target !== void 0) {
18802
+ return {
18803
+ ...base,
18804
+ path: target.candidate,
18805
+ status: "inserted",
18806
+ reason: "Mounted into the root layout.",
18807
+ newContent: insertMount(target.content, spec.importStatement, spec.jsxTag, anchor)
18808
+ };
18809
+ }
18810
+ }
18811
+ return { ...base, status: "todo", reason: "Mount manually (no single layout anchor found)." };
18812
+ };
18813
+ var planReportModeInstall = async (options) => {
18814
+ const { kitRoot, dest, surface, assistant, appSurface, fs = defaultReportModeFs } = options;
18815
+ if (!isInstallableSurface(surface)) {
18816
+ return { available: false, surface };
18817
+ }
18818
+ const sourceDir = join33(kitRoot, "templates", surface);
18819
+ const sources = SURFACE_SOURCES[surface];
18820
+ const destDeps = parseDependencies(await fs.readText(join33(dest, "package.json")));
18821
+ const rewrite = await planRewrite({ surface, dest, fs, appSurface, destDeps });
18822
+ const files = await buildPlannedFiles({
18823
+ fs,
18824
+ sourceDir,
18825
+ dest,
18826
+ sources,
18827
+ applyRewrite: rewrite.applied
18828
+ });
18829
+ if (files.length === 0) {
18830
+ throw new Error(
18831
+ `Report Mode source not found under templates/${surface}. Re-run from a kit workspace or with kit access.`
18832
+ );
18833
+ }
18834
+ const utilsFile = files.find((file) => file.relativePath === UTILS_FILE);
18835
+ const willWriteUtils = utilsFile !== void 0 && !utilsFile.exists;
18836
+ const sourceDeps = parseDependencies(await fs.readText(join33(sourceDir, "package.json")));
18837
+ const deps = buildDeps(surface, sourceDeps, willWriteUtils);
18838
+ const env = buildEnv(surface, assistant);
18839
+ const mount = await planMount(fs, buildMountSpec(surface, dest, appSurface));
18840
+ const todos = [];
18841
+ if (assistant === null) {
18842
+ todos.push(
18843
+ "Run `vybekiit doctor` to set your assistant key so Report Mode knows where to hand off."
18844
+ );
18845
+ }
18846
+ if (sources.assumedPresent.length > 0) {
18847
+ todos.push(
18848
+ `Report Mode also imports these files that ship in every VybeKiit ${surface} app: ${sources.assumedPresent.join(", ")}. Add them first if your project predates them.`
18849
+ );
18850
+ }
18851
+ if (mount.status === "todo") {
18852
+ todos.push(
18853
+ `Mount Report Mode in ${relative5(dest, mount.path) || mount.path}: add \`${mount.importSnippet}\` and render \`${mount.jsxSnippet}\` in the layout.`
18854
+ );
18855
+ }
18856
+ return {
18857
+ available: true,
18858
+ surface,
18859
+ dest,
18860
+ files,
18861
+ deps,
18862
+ env,
18863
+ rewrite,
18864
+ mount,
18865
+ assumedPresent: sources.assumedPresent,
18866
+ todos,
18867
+ nextCommands: assistant === null ? ["vybekiit doctor"] : []
18868
+ };
18869
+ };
18870
+ var defaultApplySeams = {
18871
+ fs: defaultReportModeFs,
18872
+ ensureDeps: ensureDependencies,
18873
+ writeEnv: writeEnvKeys
18874
+ };
18875
+ var applyReportModeInstall = async (plan, options = { force: false }, seams = defaultApplySeams) => {
18876
+ const outcomes = await Promise.all(
18877
+ plan.files.map(async (file) => {
18878
+ if (file.exists && !options.force) {
18879
+ return { kind: "skipped", path: file.relativePath };
18880
+ }
18881
+ await seams.fs.writeText(file.absolutePath, file.content);
18882
+ return { kind: "written", path: file.relativePath };
18883
+ })
18884
+ );
18885
+ const written = outcomes.filter((row) => row.kind === "written").map((row) => row.path);
18886
+ const skipped = outcomes.filter((row) => row.kind === "skipped").map((row) => row.path);
18887
+ const depsAdded = await seams.ensureDeps(join33(plan.dest, "package.json"), plan.deps);
18888
+ if (Object.keys(plan.env).length > 0) {
18889
+ seams.writeEnv(plan.dest, plan.env);
18890
+ }
18891
+ if (plan.mount.status === "inserted" && plan.mount.newContent !== void 0) {
18892
+ await seams.fs.writeText(plan.mount.path, plan.mount.newContent);
18893
+ }
18894
+ return {
18895
+ written,
18896
+ skipped,
18897
+ depsAdded,
18898
+ envKeys: Object.keys(plan.env),
18899
+ mount: plan.mount.status
18900
+ };
18901
+ };
18902
+
18903
+ // src/commands/reportModeCmd.ts
18904
+ var isCursorSession = () => Boolean(process14.env.CURSOR_TRACE_ID || process14.env.CURSOR_SESSION_ID);
18905
+ var succeeds = (command, args) => spawnSync(command, [...args], { stdio: "ignore" }).status === 0;
18906
+ var resolveAssistant = () => inferVybeAssistant({
18907
+ cursorSession: isCursorSession(),
18908
+ claudeInstalled: succeeds("claude", ["--version"]),
18909
+ codexInstalled: succeeds("codex", ["--version"])
18910
+ });
18911
+ var installPayload2 = (plan, written, skipped, dryRun) => ({
18912
+ ok: true,
18913
+ dryRun,
18914
+ surface: plan.surface,
18915
+ files: plan.files.map((file) => file.relativePath),
18916
+ written,
18917
+ skipped,
18918
+ deps: plan.deps,
18919
+ env: plan.env,
18920
+ mount: { status: plan.mount.status, path: plan.mount.path, reason: plan.mount.reason },
18921
+ rewrite: plan.rewrite,
18922
+ assumedPresent: plan.assumedPresent,
18923
+ todos: plan.todos,
18924
+ nextCommands: plan.nextCommands
18925
+ });
18926
+ var reportModeError = (error) => ({
18927
+ json: JSON.stringify({ ok: false, error }),
18928
+ exitCode: 1
18929
+ });
18930
+ var runAddReportMode = async (args) => {
18931
+ const flags = parsePieceFlags(args);
18932
+ const destArg = flags.to === void 0 || flags.to === "" ? flags.positionals.at(0) : flags.to;
18933
+ const dest = resolveInstallDest(destArg, process14.cwd());
18934
+ const surface = inferProjectSurfaceSync(dest).template;
18935
+ let cleanup;
18936
+ try {
18937
+ const resolved = await resolveKitSource();
18938
+ const { cleanup: resolvedCleanup, kitRoot } = resolved;
18939
+ cleanup = resolvedCleanup;
18940
+ const appSurface = surface === "web" ? await resolveAppSurface(dest) : void 0;
18941
+ const plan = await planReportModeInstall({
18942
+ kitRoot,
18943
+ dest,
18944
+ surface,
18945
+ assistant: resolveAssistant(),
18946
+ ...appSurface === void 0 ? {} : { appSurface }
18947
+ });
18948
+ if (!plan.available) {
18949
+ return {
18950
+ json: JSON.stringify(
18951
+ {
18952
+ ok: true,
18953
+ available: false,
18954
+ surface: plan.surface,
18955
+ reason: `Report Mode has no installable files for the ${plan.surface} surface (web, mobile, and extension only).`
18956
+ },
18957
+ null,
18958
+ 2
18959
+ ),
18960
+ exitCode: 0
18961
+ };
18962
+ }
18963
+ if (flags.dryRun) {
18964
+ return {
18965
+ json: JSON.stringify(installPayload2(plan, [], [], true), null, 2),
18966
+ exitCode: 0
18967
+ };
18968
+ }
18969
+ const { written, skipped } = await applyReportModeInstall(plan, { force: flags.force });
18970
+ return {
18971
+ json: JSON.stringify(installPayload2(plan, written, skipped, false), null, 2),
18972
+ exitCode: 0
18973
+ };
18974
+ } catch (error) {
18975
+ return reportModeError(caughtMessage(error));
18976
+ } finally {
18977
+ if (cleanup !== void 0) {
18978
+ await cleanup();
18979
+ }
18980
+ }
18981
+ };
18982
+
18983
+ // src/commands/piecesInteractive.ts
18984
+ var runListPath = async () => {
18985
+ const result = await runListPieces([]);
18986
+ process15.stdout.write(`${result.json}
18987
+ `);
18988
+ return result.exitCode;
18989
+ };
18990
+ var runDbPresetPath = async () => {
18991
+ const picked = await select({
18992
+ message: "Which database preset?",
18993
+ options: ALL_PRESETS.map((preset) => ({
18994
+ value: preset.id,
18995
+ label: preset.id,
18996
+ hint: preset.description === void 0 || preset.description === "" ? preset.id : preset.description
18997
+ }))
18998
+ });
18999
+ if (isCancel2(picked) || typeof picked !== "string") {
19000
+ cancel("Cancelled.");
19001
+ return 1;
19002
+ }
19003
+ const result = await runApplyPreset([picked, "--dry-run"]);
19004
+ process15.stdout.write(`${result.json}
19005
+ `);
19006
+ process15.stdout.write(
19007
+ `
19008
+ Dry-run shown. Apply for real with: vybekiit apply-preset ${picked}
19009
+ (Needs DATABASE_URL in the project.)
19010
+ `
19011
+ );
19012
+ return result.exitCode;
19013
+ };
19014
+ var runReportModePath = async () => {
19015
+ const result = await runAddReportMode(["--to=."]);
19016
+ process15.stdout.write(`${result.json}
19017
+ `);
19018
+ if (result.exitCode === 0) {
19019
+ process15.stdout.write(
19020
+ "\nInstalled Report Mode into the current folder. Wire any TODOs in the JSON report next.\n"
19021
+ );
19022
+ }
19023
+ return result.exitCode;
19024
+ };
19025
+ var runPageRecipePath = async () => {
19026
+ let cleanup;
19027
+ try {
19028
+ const resolved = await resolveKitSource();
19029
+ const { cleanup: resolvedCleanup, kitRoot } = resolved;
19030
+ cleanup = resolvedCleanup;
19031
+ const recipes = await loadPageRecipes(kitRoot);
19032
+ if (recipes.length === 0) {
19033
+ process15.stderr.write("No page recipes available from the kit source.\n");
19034
+ return 1;
19035
+ }
19036
+ const picked = await select({
19037
+ message: "Which page recipe?",
19038
+ options: recipes.map((recipe) => ({
19039
+ value: recipe.id,
19040
+ label: recipe.title,
19041
+ hint: `${recipe.groupLabel} \xB7 ${recipe.targetRoute}`
19042
+ }))
19043
+ });
19044
+ if (isCancel2(picked) || typeof picked !== "string") {
19045
+ cancel("Cancelled.");
19046
+ return 1;
19047
+ }
19048
+ const result = await runAddPageRecipe([picked, "--to=."]);
19049
+ process15.stdout.write(`${result.json}
19050
+ `);
19051
+ if (result.exitCode === 0) {
19052
+ process15.stdout.write(
19053
+ `
19054
+ Installed "${picked}" into the current folder. Wire the TODOs in the JSON report next.
19055
+ `
19056
+ );
19057
+ }
19058
+ return result.exitCode;
19059
+ } catch (error) {
19060
+ const message = caughtMessage(error);
19061
+ process15.stderr.write(`${message}
19062
+ `);
19063
+ return 1;
19064
+ } finally {
19065
+ if (cleanup !== void 0) {
19066
+ await cleanup();
19067
+ }
19068
+ }
19069
+ };
19070
+ var runAddPiecesInteractive = async () => {
19071
+ if (!isInteractive()) {
19072
+ process15.stderr.write(
19073
+ "add requires arguments in non-interactive mode. Try: vybekiit list-pieces\n"
19074
+ );
19075
+ return 1;
19076
+ }
19077
+ const kind = await select({
19078
+ message: "What kind of ready piece?",
19079
+ options: [
19080
+ {
19081
+ value: "page-recipe",
18246
19082
  label: "Page recipe (ready screen)",
18247
19083
  hint: "Copy a full page into your app"
18248
19084
  },
19085
+ {
19086
+ value: "report-mode",
19087
+ label: "Report Mode (point & fix overlay)",
19088
+ hint: "Add the dev-only inspect/report dock"
19089
+ },
18249
19090
  {
18250
19091
  value: "db",
18251
19092
  label: "Database preset",
@@ -18258,7 +19099,7 @@ var runAddPiecesInteractive = async () => {
18258
19099
  }
18259
19100
  ]
18260
19101
  });
18261
- if (isCancel(kind) || typeof kind !== "string") {
19102
+ if (isCancel2(kind) || typeof kind !== "string") {
18262
19103
  cancel("Cancelled.");
18263
19104
  return 1;
18264
19105
  }
@@ -18268,11 +19109,14 @@ var runAddPiecesInteractive = async () => {
18268
19109
  if (kind === "db") {
18269
19110
  return runDbPresetPath();
18270
19111
  }
19112
+ if (kind === "report-mode") {
19113
+ return runReportModePath();
19114
+ }
18271
19115
  return runPageRecipePath();
18272
19116
  };
18273
19117
 
18274
19118
  // src/commands/planDataModelCmd.ts
18275
- import { readFile as readFile14 } from "fs/promises";
19119
+ import { readFile as readFile17 } from "fs/promises";
18276
19120
  var PROVIDERS = [
18277
19121
  "supabase",
18278
19122
  "neon",
@@ -18302,7 +19146,7 @@ var runPlanDataModel = async (args) => {
18302
19146
  };
18303
19147
  }
18304
19148
  try {
18305
- const raw = await readFile14(inputPath, "utf8");
19149
+ const raw = await readFile17(inputPath, "utf8");
18306
19150
  const parsed = JSON.parse(raw);
18307
19151
  const { entities } = parsed;
18308
19152
  if (entities === void 0 || entities.length === 0) {
@@ -18328,9 +19172,9 @@ var runPlanDataModel = async (args) => {
18328
19172
  };
18329
19173
 
18330
19174
  // src/commands/planReadiness.ts
18331
- import { access as access12 } from "fs/promises";
18332
- import { join as join32 } from "path";
18333
- import process14 from "process";
19175
+ import { access as access13 } from "fs/promises";
19176
+ import { join as join34 } from "path";
19177
+ import process16 from "process";
18334
19178
  var FEATURES = [
18335
19179
  "sign-in",
18336
19180
  "payments",
@@ -18342,13 +19186,13 @@ var FEATURES = [
18342
19186
  var resolveFeatureName = (value) => FEATURES.find((feature) => feature === value);
18343
19187
  var pathExists7 = async (path) => {
18344
19188
  try {
18345
- await access12(path);
19189
+ await access13(path);
18346
19190
  return true;
18347
19191
  } catch {
18348
19192
  return false;
18349
19193
  }
18350
19194
  };
18351
- var runPlanReadiness = async (args, cwd = process14.cwd()) => {
19195
+ var runPlanReadiness = async (args, cwd = process16.cwd()) => {
18352
19196
  const [featureArg, templateArg] = args;
18353
19197
  const feature = featureArg === void 0 ? void 0 : resolveFeatureName(featureArg);
18354
19198
  if (feature === void 0) {
@@ -18374,7 +19218,7 @@ var runPlanReadiness = async (args, cwd = process14.cwd()) => {
18374
19218
  exitCode: 1
18375
19219
  };
18376
19220
  }
18377
- const hasBackend = await pathExists7(join32(cwd, "backend", "package.json"));
19221
+ const hasBackend = await pathExists7(join34(cwd, "backend", "package.json"));
18378
19222
  const hasWeb = inferProjectSurfaceSync(cwd).template === "web";
18379
19223
  const plan = planFeatureReadiness({
18380
19224
  template,
@@ -18417,16 +19261,16 @@ var runPlanSetup = (args) => {
18417
19261
  };
18418
19262
 
18419
19263
  // src/commands/renderAgentLayer.ts
18420
- import { mkdir as mkdir8, writeFile as writeFile9 } from "fs/promises";
18421
- import { dirname as dirname12, join as join33 } from "path";
18422
- import process15 from "process";
19264
+ import { mkdir as mkdir10, writeFile as writeFile12 } from "fs/promises";
19265
+ import { dirname as dirname13, join as join35 } from "path";
19266
+ import process17 from "process";
18423
19267
  var writeBuyerSkillStubs = async (cwd, template, skillContents) => {
18424
19268
  const stubs = planBuyerSkillStubOutputs(template, skillContents);
18425
19269
  await Promise.all(
18426
19270
  stubs.map(async (stub) => {
18427
- const absolute = join33(cwd, stub.stubPath);
18428
- await mkdir8(dirname12(absolute), { recursive: true });
18429
- await writeFile9(absolute, stub.content, "utf8");
19271
+ const absolute = join35(cwd, stub.stubPath);
19272
+ await mkdir10(dirname13(absolute), { recursive: true });
19273
+ await writeFile12(absolute, stub.content, "utf8");
18430
19274
  })
18431
19275
  );
18432
19276
  return stubs.map((stub) => stub.stubPath);
@@ -18441,7 +19285,7 @@ var resolveRenderTemplate = async (cwd, templateArg) => {
18441
19285
  }
18442
19286
  return "web";
18443
19287
  };
18444
- var runRenderAgentLayer = async (cwd = process15.cwd(), templateArg) => {
19288
+ var runRenderAgentLayer = async (cwd = process17.cwd(), templateArg) => {
18445
19289
  const template = await resolveRenderTemplate(cwd, templateArg);
18446
19290
  const { contents, present } = await loadAgentLayerRenderInputs(cwd);
18447
19291
  const skillContents = await listBuyerSkillContents(cwd);
@@ -18464,22 +19308,22 @@ var runRenderAgentLayer = async (cwd = process15.cwd(), templateArg) => {
18464
19308
  };
18465
19309
 
18466
19310
  // src/commands/setup.ts
18467
- import process24 from "process";
19311
+ import process27 from "process";
18468
19312
 
18469
19313
  // src/doctor/gate.ts
18470
- import { spawnSync } from "child_process";
18471
- import process16 from "process";
18472
- var { org: GATE_ORG, repos: GATE_REPOS } = readGateIdentity(process16.env);
19314
+ import { spawnSync as spawnSync2 } from "child_process";
19315
+ import process18 from "process";
19316
+ var { org: GATE_ORG, repos: GATE_REPOS } = readGateIdentity(process18.env);
18473
19317
  var SITE_URL = (() => {
18474
- const value = process16.env.VYBEKIIT_SITE_URL;
19318
+ const value = process18.env.VYBEKIIT_SITE_URL;
18475
19319
  if (value !== void 0 && value.trim() !== "") {
18476
19320
  return value;
18477
19321
  }
18478
19322
  return "https://vybekiit.com";
18479
19323
  })();
18480
- var ghSucceeds = (args) => spawnSync("gh", [...args], { stdio: "ignore" }).status === 0;
19324
+ var ghSucceeds = (args) => spawnSync2("gh", [...args], { stdio: "ignore" }).status === 0;
18481
19325
  var isOrgMember = () => {
18482
- const result = spawnSync("gh", ["api", `user/memberships/orgs/${GATE_ORG}`, "--jq", ".state"], {
19326
+ const result = spawnSync2("gh", ["api", `user/memberships/orgs/${GATE_ORG}`, "--jq", ".state"], {
18483
19327
  encoding: "utf8"
18484
19328
  });
18485
19329
  const stdout = result.stdout === void 0 ? "" : result.stdout;
@@ -18487,7 +19331,7 @@ var isOrgMember = () => {
18487
19331
  };
18488
19332
  var hasRepoAccess = () => GATE_REPOS.some((repo) => ghSucceeds(["api", `repos/${GATE_ORG}/${repo}`]));
18489
19333
  var checkAccess = () => {
18490
- if (process16.env.VYBEKIIT_SKIP_GATE === "1") {
19334
+ if (process18.env.VYBEKIIT_SKIP_GATE === "1") {
18491
19335
  return { allowed: true, reason: "skipped", org: GATE_ORG };
18492
19336
  }
18493
19337
  if (!ghSucceeds(["--version"])) {
@@ -18519,61 +19363,35 @@ var ensureAccessOrExit = () => {
18519
19363
  if (result.allowed) {
18520
19364
  return true;
18521
19365
  }
18522
- process16.stderr.write(`${formatGateFailure(result)}
19366
+ process18.stderr.write(`${formatGateFailure(result)}
18523
19367
  `);
18524
19368
  return false;
18525
19369
  };
18526
19370
 
18527
19371
  // src/doctor/run.ts
18528
- import { spawnSync as spawnSync7 } from "child_process";
18529
- import process19 from "process";
18530
-
18531
- // ../packages/reportMode/src/deeplink.ts
18532
- var inferVybeAssistant = (options) => {
18533
- if (options.cursorSession) {
18534
- return "cursor";
18535
- }
18536
- if (options.claudeInstalled) {
18537
- return "claude";
18538
- }
18539
- if (options.codexInstalled) {
18540
- return "codex";
18541
- }
18542
- if (options.kiroInstalled === true) {
18543
- return "kiro";
18544
- }
18545
- if (options.kimiInstalled === true) {
18546
- return "kimi";
18547
- }
18548
- if (options.grokInstalled === true) {
18549
- return "grok";
18550
- }
18551
- if (options.devinInstalled === true) {
18552
- return "devin";
18553
- }
18554
- return null;
18555
- };
19372
+ import { spawnSync as spawnSync8 } from "child_process";
19373
+ import process21 from "process";
18556
19374
 
18557
19375
  // src/doctor/agentExperience.ts
18558
- import { spawnSync as spawnSync3 } from "child_process";
19376
+ import { spawnSync as spawnSync4 } from "child_process";
18559
19377
  import { accessSync, constants } from "fs";
18560
19378
  import { homedir } from "os";
18561
- import { join as join35 } from "path";
19379
+ import { join as join37 } from "path";
18562
19380
 
18563
19381
  // src/doctor/mcpWire.ts
18564
- import { spawnSync as spawnSync2 } from "child_process";
19382
+ import { spawnSync as spawnSync3 } from "child_process";
18565
19383
  import { existsSync as existsSync7, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
18566
- import { dirname as dirname13, join as join34 } from "path";
19384
+ import { dirname as dirname14, join as join36 } from "path";
18567
19385
  var CATALOG_RELATIVE_PATHS = [
18568
- join34(".claude", "mcp", "mcp-servers.json"),
19386
+ join36(".claude", "mcp", "mcp-servers.json"),
18569
19387
  "mcp-servers.json"
18570
19388
  ];
18571
19389
  var defaultCommandExists = (command) => {
18572
- const version = spawnSync2(command, ["--version"], { stdio: "ignore" });
19390
+ const version = spawnSync3(command, ["--version"], { stdio: "ignore" });
18573
19391
  if (version.status === 0) {
18574
19392
  return true;
18575
19393
  }
18576
- const help = spawnSync2(command, ["--help"], { stdio: "ignore" });
19394
+ const help = spawnSync3(command, ["--help"], { stdio: "ignore" });
18577
19395
  return help.status === 0 || help.error === void 0;
18578
19396
  };
18579
19397
  var createDefaultMcpWireDeps = () => ({
@@ -18587,7 +19405,7 @@ var createDefaultMcpWireDeps = () => ({
18587
19405
  },
18588
19406
  commandExists: defaultCommandExists,
18589
19407
  spawn: (command, args, options) => {
18590
- const result = spawnSync2(command, [...args], {
19408
+ const result = spawnSync3(command, [...args], {
18591
19409
  stdio: "ignore",
18592
19410
  cwd: options?.cwd,
18593
19411
  timeout: 8e3,
@@ -18597,8 +19415,8 @@ var createDefaultMcpWireDeps = () => ({
18597
19415
  }
18598
19416
  });
18599
19417
  var findMcpCatalogPath = (cwd, pathExists9) => {
18600
- for (const relative4 of CATALOG_RELATIVE_PATHS) {
18601
- const absolute = join34(cwd, relative4);
19418
+ for (const relative6 of CATALOG_RELATIVE_PATHS) {
19419
+ const absolute = join36(cwd, relative6);
18602
19420
  if (pathExists9(absolute)) {
18603
19421
  return absolute;
18604
19422
  }
@@ -18745,7 +19563,7 @@ var writeMergedMcpConfig = (configPath, core, deps) => {
18745
19563
  if (added.length === 0 && deps.pathExists(configPath)) {
18746
19564
  return { written: false, added: [] };
18747
19565
  }
18748
- deps.mkdir(dirname13(configPath));
19566
+ deps.mkdir(dirname14(configPath));
18749
19567
  deps.writeFile(configPath, formatMcpServersConfig(config));
18750
19568
  return { written: true, added };
18751
19569
  };
@@ -18803,7 +19621,7 @@ var wireCoreMcps = (cwd, agents, deps = createDefaultMcpWireDeps()) => {
18803
19621
  let anyFailure = false;
18804
19622
  for (const agent of capable) {
18805
19623
  if (agent.id === "cursor") {
18806
- const configPath = join34(cwd, ".cursor", "mcp.json");
19624
+ const configPath = join36(cwd, ".cursor", "mcp.json");
18807
19625
  try {
18808
19626
  const { written, added } = writeMergedMcpConfig(configPath, core, deps);
18809
19627
  agentsWired.push("cursor");
@@ -18821,7 +19639,7 @@ var wireCoreMcps = (cwd, agents, deps = createDefaultMcpWireDeps()) => {
18821
19639
  continue;
18822
19640
  }
18823
19641
  if (agent.id === "claude-code") {
18824
- const configPath = join34(cwd, ".mcp.json");
19642
+ const configPath = join36(cwd, ".mcp.json");
18825
19643
  try {
18826
19644
  const { written, added } = writeMergedMcpConfig(configPath, core, deps);
18827
19645
  if (written && added.length > 0) {
@@ -18859,11 +19677,11 @@ var wireCoreMcps = (cwd, agents, deps = createDefaultMcpWireDeps()) => {
18859
19677
 
18860
19678
  // src/doctor/agentExperience.ts
18861
19679
  var defaultCommandExists2 = (command) => {
18862
- const version = spawnSync3(command, ["--version"], { stdio: "ignore" });
19680
+ const version = spawnSync4(command, ["--version"], { stdio: "ignore" });
18863
19681
  if (version.status === 0) {
18864
19682
  return true;
18865
19683
  }
18866
- const help = spawnSync3(command, ["--help"], { stdio: "ignore" });
19684
+ const help = spawnSync4(command, ["--help"], { stdio: "ignore" });
18867
19685
  return help.status === 0 || help.error === void 0;
18868
19686
  };
18869
19687
  var defaultPathExists = (path) => {
@@ -18910,22 +19728,22 @@ var detectPresentAgents = (cwd, deps = createDefaultAgentExperienceDeps()) => {
18910
19728
  add("gemini");
18911
19729
  }
18912
19730
  const home = homedir();
18913
- if (deps.pathExists(join35(home, ".claude"))) {
19731
+ if (deps.pathExists(join37(home, ".claude"))) {
18914
19732
  add("claude-code");
18915
19733
  }
18916
- if (deps.pathExists(join35(home, ".codex"))) {
19734
+ if (deps.pathExists(join37(home, ".codex"))) {
18917
19735
  add("codex");
18918
19736
  }
18919
- if (deps.pathExists(join35(home, ".cursor"))) {
19737
+ if (deps.pathExists(join37(home, ".cursor"))) {
18920
19738
  add("cursor");
18921
19739
  }
18922
- if (deps.pathExists(join35(cwd, ".claude"))) {
19740
+ if (deps.pathExists(join37(cwd, ".claude"))) {
18923
19741
  add("claude-code");
18924
19742
  }
18925
- if (deps.pathExists(join35(cwd, ".cursor"))) {
19743
+ if (deps.pathExists(join37(cwd, ".cursor"))) {
18926
19744
  add("cursor");
18927
19745
  }
18928
- if (deps.pathExists(join35(cwd, "AGENTS.md"))) {
19746
+ if (deps.pathExists(join37(cwd, "AGENTS.md"))) {
18929
19747
  add("codex");
18930
19748
  }
18931
19749
  if (found.size === 0) {
@@ -18951,7 +19769,7 @@ var runAgentExperience = async (cwd, options, deps = createDefaultAgentExperienc
18951
19769
  let ok = true;
18952
19770
  const names = agents.map((agent) => agent.name).join(", ");
18953
19771
  lines.push(`\u2713 agents detected - ${names}`);
18954
- const hasProjectSkills = deps.pathExists(join35(cwd, ".agents", "skills")) || deps.pathExists(join35(cwd, "platform-skills.manifest.json")) || deps.pathExists(join35(cwd, "skills-lock.json"));
19772
+ const hasProjectSkills = deps.pathExists(join37(cwd, ".agents", "skills")) || deps.pathExists(join37(cwd, "platform-skills.manifest.json")) || deps.pathExists(join37(cwd, "skills-lock.json"));
18955
19773
  if (hasProjectSkills) {
18956
19774
  try {
18957
19775
  await deps.ensureProjectSkillLinks(cwd);
@@ -19003,17 +19821,17 @@ var runAgentExperience = async (cwd, options, deps = createDefaultAgentExperienc
19003
19821
  );
19004
19822
  }
19005
19823
  }
19006
- const kitRootAgentMcp = join35(cwd, "packages", "agentMcp");
19007
- const surfaceAgentMcp = join35(cwd, "..", "..", "packages", "agentMcp");
19824
+ const kitRootAgentMcp = join37(cwd, "packages", "agentMcp");
19825
+ const surfaceAgentMcp = join37(cwd, "..", "..", "packages", "agentMcp");
19008
19826
  const hasKitRootMcp = deps.pathExists(kitRootAgentMcp);
19009
19827
  const hasSurfaceMcp = deps.pathExists(surfaceAgentMcp);
19010
19828
  if (hasKitRootMcp || hasSurfaceMcp) {
19011
19829
  try {
19012
19830
  const layout = hasKitRootMcp ? "kit-root" : "surface";
19013
19831
  const template = layout === "kit-root" ? ["web", "mobile", "extension", "backend", "spa"].find(
19014
- (name) => deps.pathExists(join35(cwd, "templates", name))
19832
+ (name) => deps.pathExists(join37(cwd, "templates", name))
19015
19833
  ) : void 0;
19016
- const configPaths = [join35(cwd, ".cursor", "mcp.json"), join35(cwd, ".mcp.json")];
19834
+ const configPaths = [join37(cwd, ".cursor", "mcp.json"), join37(cwd, ".mcp.json")];
19017
19835
  for (const configPath of configPaths) {
19018
19836
  await writeFirstPartyMcpConfigFile(
19019
19837
  configPath,
@@ -19035,7 +19853,7 @@ var runAgentExperience = async (cwd, options, deps = createDefaultAgentExperienc
19035
19853
 
19036
19854
  // src/doctor/assetsValidate.ts
19037
19855
  import { existsSync as existsSync8, readFileSync as readFileSync8 } from "fs";
19038
- import { join as join36 } from "path";
19856
+ import { join as join38 } from "path";
19039
19857
  var ASSET_SURFACE_DIRS = {
19040
19858
  web: "public",
19041
19859
  spa: "public",
@@ -19056,9 +19874,9 @@ var OPTIMIZE_FILE_CANDIDATES = [
19056
19874
  "scripts/optimize.ts"
19057
19875
  ];
19058
19876
  var createDefaultAssetsValidateDeps = (cwd) => ({
19059
- exists: (relativePath) => existsSync8(join36(cwd, relativePath)),
19877
+ exists: (relativePath) => existsSync8(join38(cwd, relativePath)),
19060
19878
  readUtf8: (relativePath) => {
19061
- const absolute = join36(cwd, relativePath);
19879
+ const absolute = join38(cwd, relativePath);
19062
19880
  if (!existsSync8(absolute)) {
19063
19881
  return null;
19064
19882
  }
@@ -19197,35 +20015,35 @@ var verifyAssetsPipeline = (cwd, surface = inferProjectSurfaceSync(cwd), deps =
19197
20015
 
19198
20016
  // src/global/globalPaths.ts
19199
20017
  import { homedir as homedir2 } from "os";
19200
- import { dirname as dirname14, join as join37 } from "path";
19201
- import process17 from "process";
20018
+ import { dirname as dirname15, join as join39 } from "path";
20019
+ import process19 from "process";
19202
20020
  import { fileURLToPath as fileURLToPath7 } from "url";
19203
- var MODULE_DIR = dirname14(fileURLToPath7(import.meta.url));
20021
+ var MODULE_DIR = dirname15(fileURLToPath7(import.meta.url));
19204
20022
  var resolveConfigDir = () => {
19205
- const override = process17.env.CLAUDE_CONFIG_DIR;
20023
+ const override = process19.env.CLAUDE_CONFIG_DIR;
19206
20024
  if (override !== void 0 && override.trim() !== "") {
19207
20025
  return override.trim();
19208
20026
  }
19209
- return join37(homedir2(), ".claude");
20027
+ return join39(homedir2(), ".claude");
19210
20028
  };
19211
20029
  var resolveGlobalPaths = (configDir = resolveConfigDir()) => ({
19212
20030
  configDir,
19213
- skillsDir: join37(configDir, "skills"),
19214
- commandsDir: join37(configDir, "commands"),
19215
- memoryFile: join37(configDir, "CLAUDE.md"),
19216
- settingsFile: join37(configDir, "settings.json"),
20031
+ skillsDir: join39(configDir, "skills"),
20032
+ commandsDir: join39(configDir, "commands"),
20033
+ memoryFile: join39(configDir, "CLAUDE.md"),
20034
+ settingsFile: join39(configDir, "settings.json"),
19217
20035
  // At runtime this module is inlined into dist/bin.js, so MODULE_DIR is <install>/dist
19218
20036
  // and the payload sits beside it at dist/global-skills.
19219
- bundledSkillsDir: join37(MODULE_DIR, "global-skills")
20037
+ bundledSkillsDir: join39(MODULE_DIR, "global-skills")
19220
20038
  });
19221
20039
 
19222
20040
  // src/global/globalStatus.ts
19223
- import { readFile as readFile15, stat as stat2 } from "fs/promises";
19224
- import { join as join39 } from "path";
20041
+ import { readFile as readFile18, stat as stat2 } from "fs/promises";
20042
+ import { join as join41 } from "path";
19225
20043
 
19226
20044
  // src/global/managedSkills.ts
19227
- import { readdir as readdir8, stat } from "fs/promises";
19228
- import { join as join38 } from "path";
20045
+ import { readdir as readdir9, stat } from "fs/promises";
20046
+ import { join as join40 } from "path";
19229
20047
  var GLOBAL_SKILL_SAMPLE_SIZE = 5;
19230
20048
  var MANAGED_SKILL_MARKER = ".vybekiit-managed";
19231
20049
  var exists = async (path) => {
@@ -19238,13 +20056,13 @@ var exists = async (path) => {
19238
20056
  };
19239
20057
  var listManagedSkillNames = async (skillsDir) => {
19240
20058
  try {
19241
- const entries = await readdir8(skillsDir, { withFileTypes: true });
20059
+ const entries = await readdir9(skillsDir, { withFileTypes: true });
19242
20060
  const names = [];
19243
20061
  for (const entry of entries) {
19244
20062
  if (!entry.isDirectory()) {
19245
20063
  continue;
19246
20064
  }
19247
- if (await exists(join38(skillsDir, entry.name, MANAGED_SKILL_MARKER))) {
20065
+ if (await exists(join40(skillsDir, entry.name, MANAGED_SKILL_MARKER))) {
19248
20066
  names.push(entry.name);
19249
20067
  }
19250
20068
  }
@@ -19259,6 +20077,7 @@ var sampleManagedSkillNames = (names, size = GLOBAL_SKILL_SAMPLE_SIZE) => {
19259
20077
  return [];
19260
20078
  }
19261
20079
  const preferred = [
20080
+ "feedback",
19262
20081
  "onboarding",
19263
20082
  "plan-my-idea",
19264
20083
  "setup-payments",
@@ -19284,13 +20103,13 @@ var exists2 = async (path) => {
19284
20103
  var readGlobalStatus = async (paths) => {
19285
20104
  let hasMemory = false;
19286
20105
  try {
19287
- hasMemory = (await readFile15(paths.memoryFile, "utf8")).includes("BEGIN VYBEKIIT");
20106
+ hasMemory = (await readFile18(paths.memoryFile, "utf8")).includes("BEGIN VYBEKIIT");
19288
20107
  } catch {
19289
20108
  hasMemory = false;
19290
20109
  }
19291
20110
  const managed = await listManagedSkillNames(paths.skillsDir);
19292
20111
  return {
19293
- hasCommand: await exists2(join39(paths.commandsDir, "vybekiit.md")),
20112
+ hasCommand: await exists2(join41(paths.commandsDir, "vybekiit.md")),
19294
20113
  hasMemory,
19295
20114
  skillCount: managed.length,
19296
20115
  skillSample: sampleManagedSkillNames(managed)
@@ -19309,9 +20128,9 @@ var formatGlobalStatus = (status) => {
19309
20128
  };
19310
20129
 
19311
20130
  // src/doctor/codexConfig.ts
19312
- import { access as access13, mkdir as mkdir9, readFile as readFile16, writeFile as writeFile10 } from "fs/promises";
20131
+ import { access as access14, mkdir as mkdir11, readFile as readFile19, writeFile as writeFile13 } from "fs/promises";
19313
20132
  import { homedir as homedir3 } from "os";
19314
- import { join as join40 } from "path";
20133
+ import { join as join42 } from "path";
19315
20134
  var FEATURES_BLOCK = ["[features]", "skills = true"].join("\n");
19316
20135
  var FEATURES_SKILLS_ENABLED_PATTERN = /\[features\][\s\S]*?\bskills\s*=\s*true\b/m;
19317
20136
  var FEATURES_BLOCK_PATTERN = /(\[features\][^[]*)/m;
@@ -19320,10 +20139,10 @@ var SKILLS_LINE_PATTERN = /\bskills\s*=\s*.*/m;
19320
20139
  var codexConfigPath = () => {
19321
20140
  const configuredHome = process.env.CODEX_HOME;
19322
20141
  if (configuredHome !== void 0 && configuredHome.trim() !== "") {
19323
- return join40(configuredHome.trim(), "config.toml");
20142
+ return join42(configuredHome.trim(), "config.toml");
19324
20143
  }
19325
- const home = join40(homedir3(), ".codex");
19326
- return join40(home, "config.toml");
20144
+ const home = join42(homedir3(), ".codex");
20145
+ return join42(home, "config.toml");
19327
20146
  };
19328
20147
  var upsertFeaturesSkills = (content) => {
19329
20148
  if (FEATURES_SKILLS_ENABLED_PATTERN.test(content)) {
@@ -19349,10 +20168,10 @@ ${FEATURES_BLOCK}
19349
20168
  };
19350
20169
  var ensureCodexSkillsEnabled = async () => {
19351
20170
  const path = codexConfigPath();
19352
- await mkdir9(join40(path, ".."), { recursive: true });
20171
+ await mkdir11(join42(path, ".."), { recursive: true });
19353
20172
  let previous = "";
19354
20173
  try {
19355
- previous = await readFile16(path, "utf8");
20174
+ previous = await readFile19(path, "utf8");
19356
20175
  } catch (error) {
19357
20176
  if (!(error instanceof Error && "code" in error) || error.code !== "ENOENT") {
19358
20177
  throw error;
@@ -19362,13 +20181,13 @@ var ensureCodexSkillsEnabled = async () => {
19362
20181
  if (next === previous) {
19363
20182
  return { updated: false, path };
19364
20183
  }
19365
- await writeFile10(path, next, "utf8");
20184
+ await writeFile13(path, next, "utf8");
19366
20185
  return { updated: true, path };
19367
20186
  };
19368
20187
 
19369
20188
  // src/doctor/kitWorkspaceHealth.ts
19370
20189
  import { existsSync as existsSync9, readdirSync as readdirSync2, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
19371
- import { join as join41 } from "path";
20190
+ import { join as join43 } from "path";
19372
20191
  var readPackageJsonSafe = (packageJsonPath) => {
19373
20192
  if (!existsSync9(packageJsonPath)) {
19374
20193
  return null;
@@ -19401,7 +20220,7 @@ var listPackageRelDirs = (packagesRoot) => {
19401
20220
  const top = readdirSync2(packagesRoot);
19402
20221
  const rels = [];
19403
20222
  for (const entry of top) {
19404
- const abs = join41(packagesRoot, entry);
20223
+ const abs = join43(packagesRoot, entry);
19405
20224
  let isDir = false;
19406
20225
  try {
19407
20226
  isDir = statSync2(abs).isDirectory();
@@ -19411,7 +20230,7 @@ var listPackageRelDirs = (packagesRoot) => {
19411
20230
  if (!isDir) {
19412
20231
  continue;
19413
20232
  }
19414
- if (existsSync9(join41(abs, "package.json"))) {
20233
+ if (existsSync9(join43(abs, "package.json"))) {
19415
20234
  rels.push(entry);
19416
20235
  continue;
19417
20236
  }
@@ -19422,10 +20241,10 @@ var listPackageRelDirs = (packagesRoot) => {
19422
20241
  continue;
19423
20242
  }
19424
20243
  for (const child of nested) {
19425
- const childAbs = join41(abs, child);
20244
+ const childAbs = join43(abs, child);
19426
20245
  try {
19427
- if (statSync2(childAbs).isDirectory() && existsSync9(join41(childAbs, "package.json"))) {
19428
- rels.push(join41(entry, child));
20246
+ if (statSync2(childAbs).isDirectory() && existsSync9(join43(childAbs, "package.json"))) {
20247
+ rels.push(join43(entry, child));
19429
20248
  }
19430
20249
  } catch {
19431
20250
  }
@@ -19434,15 +20253,15 @@ var listPackageRelDirs = (packagesRoot) => {
19434
20253
  return rels;
19435
20254
  };
19436
20255
  var findMissingDistPackages = (cwd) => {
19437
- const packagesRoot = join41(cwd, "packages");
20256
+ const packagesRoot = join43(cwd, "packages");
19438
20257
  const missing = [];
19439
20258
  for (const relDir of listPackageRelDirs(packagesRoot)) {
19440
- const packageDir = join41(packagesRoot, relDir);
19441
- const pkg = readPackageJsonSafe(join41(packageDir, "package.json"));
20259
+ const packageDir = join43(packagesRoot, relDir);
20260
+ const pkg = readPackageJsonSafe(join43(packageDir, "package.json"));
19442
20261
  if (pkg === null || !packageExpectsDist(pkg)) {
19443
20262
  continue;
19444
20263
  }
19445
- if (!existsSync9(join41(packageDir, "dist"))) {
20264
+ if (!existsSync9(join43(packageDir, "dist"))) {
19446
20265
  const name = typeof pkg.name === "string" ? pkg.name : relDir;
19447
20266
  missing.push({ name, relDir });
19448
20267
  }
@@ -19450,7 +20269,7 @@ var findMissingDistPackages = (cwd) => {
19450
20269
  return missing;
19451
20270
  };
19452
20271
  var verifyKitWorkspaceHealth = (cwd) => {
19453
- const packagesRoot = join41(cwd, "packages");
20272
+ const packagesRoot = join43(cwd, "packages");
19454
20273
  if (!existsSync9(packagesRoot)) {
19455
20274
  return { ok: true, lines: [] };
19456
20275
  }
@@ -19468,7 +20287,7 @@ var verifyKitWorkspaceHealth = (cwd) => {
19468
20287
  );
19469
20288
  }
19470
20289
  const buildRoots = ["tsconfig.base.json", "scripts/lib/tsupWorkspaceAliases.mjs"];
19471
- const missingRoots = buildRoots.filter((rel) => !existsSync9(join41(cwd, rel)));
20290
+ const missingRoots = buildRoots.filter((rel) => !existsSync9(join43(cwd, rel)));
19472
20291
  if (missingRoots.length > 0 && missing.length > 0) {
19473
20292
  lines.push(
19474
20293
  `\u2717 Kit is also missing rebuild helpers (${missingRoots.join(", ")}). Re-run \`vybekiit create app\` with a current CLI so build roots ship with the workspace.`
@@ -19528,12 +20347,12 @@ var verifyMobilePublishReadiness = (platform, env, probe) => {
19528
20347
  }
19529
20348
  return { ok, lines };
19530
20349
  };
19531
- var createDefaultCommandProbe = (spawnSync9) => ({
20350
+ var createDefaultCommandProbe = (spawnSync10) => ({
19532
20351
  succeeds(command, args) {
19533
- return spawnSync9(command, args, { encoding: "utf8", stdio: "pipe" }).status === 0;
20352
+ return spawnSync10(command, args, { encoding: "utf8", stdio: "pipe" }).status === 0;
19534
20353
  },
19535
20354
  output(command, args) {
19536
- const result = spawnSync9(command, args, { encoding: "utf8", stdio: "pipe" });
20355
+ const result = spawnSync10(command, args, { encoding: "utf8", stdio: "pipe" });
19537
20356
  return `${result.stdout}
19538
20357
  ${result.stderr}`.trim();
19539
20358
  }
@@ -19617,11 +20436,11 @@ var mergeDoctorTools = (providerTools, nativeTools) => {
19617
20436
 
19618
20437
  // src/doctor/perfReadiness.ts
19619
20438
  import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
19620
- import { join as join42 } from "path";
20439
+ import { join as join44 } from "path";
19621
20440
  var createDefaultPerfReadinessDeps = (cwd) => ({
19622
- exists: (relativePath) => existsSync10(join42(cwd, relativePath)),
20441
+ exists: (relativePath) => existsSync10(join44(cwd, relativePath)),
19623
20442
  readUtf8: (relativePath) => {
19624
- const absolute = join42(cwd, relativePath);
20443
+ const absolute = join44(cwd, relativePath);
19625
20444
  if (!existsSync10(absolute)) {
19626
20445
  return null;
19627
20446
  }
@@ -19754,17 +20573,17 @@ var reportFor = (reports, name) => reports.find((r) => r.tool === name);
19754
20573
 
19755
20574
  // src/doctor/platformSkills.ts
19756
20575
  import { existsSync as existsSync11, readFileSync as readFileSync11 } from "fs";
19757
- import { join as join43 } from "path";
19758
- import process18 from "process";
20576
+ import { join as join45 } from "path";
20577
+ import process20 from "process";
19759
20578
  var readManifest = (cwd) => {
19760
- const path = join43(cwd, "platform-skills.manifest.json");
20579
+ const path = join45(cwd, "platform-skills.manifest.json");
19761
20580
  if (!existsSync11(path)) {
19762
20581
  return null;
19763
20582
  }
19764
20583
  return JSON.parse(readFileSync11(path, "utf8"));
19765
20584
  };
19766
20585
  var readSkillsLock = (cwd) => {
19767
- const path = join43(cwd, "skills-lock.json");
20586
+ const path = join45(cwd, "skills-lock.json");
19768
20587
  if (!existsSync11(path)) {
19769
20588
  return null;
19770
20589
  }
@@ -19774,7 +20593,7 @@ var readSkillsLock = (cwd) => {
19774
20593
  return null;
19775
20594
  }
19776
20595
  };
19777
- var skillFileExists = (cwd, name) => existsSync11(join43(cwd, ".agents", "skills", name, "SKILL.md"));
20596
+ var skillFileExists = (cwd, name) => existsSync11(join45(cwd, ".agents", "skills", name, "SKILL.md"));
19778
20597
  var verifyPlatformSkills = (cwd) => {
19779
20598
  const manifest = readManifest(cwd);
19780
20599
  if (manifest === null) {
@@ -19798,7 +20617,7 @@ var verifyPlatformSkills = (cwd) => {
19798
20617
  };
19799
20618
  };
19800
20619
  var templateLabelForPlatformSkills = (cwd) => {
19801
- if (!existsSync11(join43(cwd, "platform-skills.manifest.json"))) {
20620
+ if (!existsSync11(join45(cwd, "platform-skills.manifest.json"))) {
19802
20621
  return null;
19803
20622
  }
19804
20623
  return inferProjectSurfaceSync(cwd).template;
@@ -19808,7 +20627,7 @@ var formatPlatformSkillsReport = (report) => {
19808
20627
  return [];
19809
20628
  }
19810
20629
  const lines = [];
19811
- const lockPath = join43(process18.cwd(), "skills-lock.json");
20630
+ const lockPath = join45(process20.cwd(), "skills-lock.json");
19812
20631
  if (existsSync11(lockPath)) {
19813
20632
  try {
19814
20633
  const lock = JSON.parse(readFileSync11(lockPath, "utf8"));
@@ -19865,10 +20684,10 @@ var formatProductSurfaceHints = (env) => {
19865
20684
 
19866
20685
  // src/doctor/projectHealth.ts
19867
20686
  import { existsSync as existsSync12, readFileSync as readFileSync12 } from "fs";
19868
- import { join as join44 } from "path";
20687
+ import { join as join46 } from "path";
19869
20688
  var GITIGNORE_ENV_LINE_PATTERN = /^\.env/m;
19870
20689
  var gitignoreCoversEnv = (cwd) => {
19871
- const path = join44(cwd, ".gitignore");
20690
+ const path = join46(cwd, ".gitignore");
19872
20691
  if (!existsSync12(path)) {
19873
20692
  return false;
19874
20693
  }
@@ -19876,7 +20695,7 @@ var gitignoreCoversEnv = (cwd) => {
19876
20695
  return GITIGNORE_ENV_LINE_PATTERN.test(content) || content.includes(".env\n") || content.includes(".env\r\n");
19877
20696
  };
19878
20697
  var cursorignoreCoversEnv = (cwd) => {
19879
- const path = join44(cwd, ".cursorignore");
20698
+ const path = join46(cwd, ".cursorignore");
19880
20699
  if (!existsSync12(path)) {
19881
20700
  return false;
19882
20701
  }
@@ -19904,7 +20723,7 @@ var verifyProjectHealth = (cwd) => {
19904
20723
  };
19905
20724
 
19906
20725
  // src/doctor/railwayAgentSetup.ts
19907
- import { spawnSync as spawnSync4 } from "child_process";
20726
+ import { spawnSync as spawnSync5 } from "child_process";
19908
20727
  var isRailwayStackActive2 = (env) => isRailwayStackActive(env);
19909
20728
  var verifyCoupledStack = (env) => {
19910
20729
  const { HOSTING_PROVIDER } = parseEnv(hostingConfigSchema, env);
@@ -19932,7 +20751,7 @@ var runRailwayAgentSetup = (railwayInstalled, railwayAuthed) => {
19932
20751
  message: "\u2192 Railway agent setup skipped - sign in with `railway login` first."
19933
20752
  };
19934
20753
  }
19935
- const result = spawnSync4("railway", ["setup", "agent", "-y"], {
20754
+ const result = spawnSync5("railway", ["setup", "agent", "-y"], {
19936
20755
  stdio: "pipe",
19937
20756
  encoding: "utf8"
19938
20757
  });
@@ -19964,17 +20783,17 @@ var formatRailwayStackReport = (env, agentSetup) => {
19964
20783
  };
19965
20784
 
19966
20785
  // src/doctor/runNativeProjectSetup.ts
19967
- import { spawnSync as spawnSync5 } from "child_process";
20786
+ import { spawnSync as spawnSync6 } from "child_process";
19968
20787
  import { existsSync as existsSync13 } from "fs";
19969
- import { join as join45 } from "path";
20788
+ import { join as join47 } from "path";
19970
20789
  var runCommand = (options) => {
19971
20790
  const { args, command, cwd, label, log } = options;
19972
20791
  log.log(`[doctor] ${label}: ${command} ${args.join(" ")}`);
19973
- const result = spawnSync5(command, [...args], { cwd, stdio: "inherit" });
20792
+ const result = spawnSync6(command, [...args], { cwd, stdio: "inherit" });
19974
20793
  return result.status === 0;
19975
20794
  };
19976
20795
  var runExtensionSetup = (cwd, log) => {
19977
- const wxtTypes = join45(cwd, ".wxt", "wxt.d.ts");
20796
+ const wxtTypes = join47(cwd, ".wxt", "wxt.d.ts");
19978
20797
  if (existsSync13(wxtTypes)) {
19979
20798
  return ["\u2713 Extension - WXT types already generated."];
19980
20799
  }
@@ -19993,7 +20812,7 @@ var runMobileSetup = (cwd, platform, log) => {
19993
20812
  if (platform !== "darwin") {
19994
20813
  return [];
19995
20814
  }
19996
- const podfile = join45(cwd, "ios", "Podfile");
20815
+ const podfile = join47(cwd, "ios", "Podfile");
19997
20816
  if (!existsSync13(podfile)) {
19998
20817
  return [
19999
20818
  "\u2192 Mobile - no `ios/` folder yet. Run `pnpm ios` (Simulator) or `npx expo prebuild --platform ios` before store builds."
@@ -20002,7 +20821,7 @@ var runMobileSetup = (cwd, platform, log) => {
20002
20821
  const ok = runCommand({
20003
20822
  log,
20004
20823
  label: "installing iOS pods",
20005
- cwd: join45(cwd, "ios"),
20824
+ cwd: join47(cwd, "ios"),
20006
20825
  command: "pod",
20007
20826
  args: ["install"]
20008
20827
  });
@@ -20025,16 +20844,16 @@ var runNativeProjectSetup = (cwd, surface, platform, log = console) => {
20025
20844
  };
20026
20845
 
20027
20846
  // src/doctor/storageR2.ts
20028
- import { spawnSync as spawnSync6 } from "child_process";
20847
+ import { spawnSync as spawnSync7 } from "child_process";
20029
20848
  import { readFileSync as readFileSync13 } from "fs";
20030
- import { join as join46 } from "path";
20849
+ import { join as join48 } from "path";
20031
20850
  var R2_BUCKET_UNSAFE_PATTERN = /[^a-z0-9-]/g;
20032
20851
  var R2_BUCKET_DASH_RUN_PATTERN = /-+/g;
20033
20852
  var R2_BUCKET_EDGE_DASH_PATTERN = /^-|-$/g;
20034
20853
  var sanitizeBucketName = (name) => name.toLowerCase().replace(R2_BUCKET_UNSAFE_PATTERN, "-").replace(R2_BUCKET_DASH_RUN_PATTERN, "-").replace(R2_BUCKET_EDGE_DASH_PATTERN, "").slice(0, 40);
20035
20854
  var readProjectName = (cwd) => {
20036
20855
  try {
20037
- const pkg = JSON.parse(readFileSync13(join46(cwd, "package.json"), "utf8"));
20856
+ const pkg = JSON.parse(readFileSync13(join48(cwd, "package.json"), "utf8"));
20038
20857
  if (pkg.name !== void 0 && pkg.name !== "" && pkg.name !== "my-vybekiit-app") {
20039
20858
  return sanitizeBucketName(pkg.name);
20040
20859
  }
@@ -20042,7 +20861,7 @@ var readProjectName = (cwd) => {
20042
20861
  }
20043
20862
  return "vybekiit-app";
20044
20863
  };
20045
- var wranglerOk = (args) => spawnSync6("wrangler", [...args], { stdio: "ignore" }).status === 0;
20864
+ var wranglerOk = (args) => spawnSync7("wrangler", [...args], { stdio: "ignore" }).status === 0;
20046
20865
  var createR2ApiToken = async (accountId, apiToken, bucketName) => {
20047
20866
  const response = await fetch(
20048
20867
  `https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/tokens`,
@@ -20601,12 +21420,12 @@ var verifyPresetsDoctor = async (env) => {
20601
21420
 
20602
21421
  // src/doctor/run.ts
20603
21422
  var toPlatform = (platform) => platform === "darwin" || platform === "win32" || platform === "linux" ? platform : null;
20604
- var isCursorSession = () => Boolean(process19.env.CURSOR_TRACE_ID || process19.env.CURSOR_SESSION_ID);
20605
- var succeeds = (command, args) => spawnSync7(command, [...args], { stdio: "ignore" }).status === 0;
21423
+ var isCursorSession2 = () => Boolean(process21.env.CURSOR_TRACE_ID || process21.env.CURSOR_SESSION_ID);
21424
+ var succeeds2 = (command, args) => spawnSync8(command, [...args], { stdio: "ignore" }).status === 0;
20606
21425
  var errorCode = (error) => error !== void 0 && "code" in error && typeof error.code === "string" ? error.code : void 0;
20607
21426
  var runInstall = (action, log) => {
20608
21427
  log.log(`[doctor] setting up ${action.tool}: ${action.command} ${action.args.join(" ")}`);
20609
- const result = spawnSync7(action.command, [...action.args], { stdio: "inherit" });
21428
+ const result = spawnSync8(action.command, [...action.args], { stdio: "inherit" });
20610
21429
  if (errorCode(result.error) === "ENOENT") {
20611
21430
  return action.requires ? { ok: false, missingRequirement: action.requires } : { ok: false };
20612
21431
  }
@@ -20630,7 +21449,7 @@ var buildReport = (tool, presence, installs) => {
20630
21449
  if (tool.auth === void 0) {
20631
21450
  return { tool: tool.name, purpose: tool.purpose, installed: true, authed: null };
20632
21451
  }
20633
- const authed = succeeds(tool.auth.command, tool.auth.args);
21452
+ const authed = succeeds2(tool.auth.command, tool.auth.args);
20634
21453
  return {
20635
21454
  tool: tool.name,
20636
21455
  purpose: tool.purpose,
@@ -20654,7 +21473,7 @@ var runToolchain = (platform, surface, env, log) => {
20654
21473
  const toolchain = mergeAgentAndProviderTools(providerAndNative);
20655
21474
  const presence = toolchain.map((tool) => ({
20656
21475
  tool: tool.name,
20657
- present: succeeds(tool.name, tool.versionArgs)
21476
+ present: succeeds2(tool.name, tool.versionArgs)
20658
21477
  }));
20659
21478
  const installs = /* @__PURE__ */ new Map();
20660
21479
  for (const action of planInstall(platform, presence, toolchain)) {
@@ -20670,7 +21489,7 @@ var verifyMobilePublishing = (platform, env, mobile, log) => {
20670
21489
  if (!mobile) {
20671
21490
  return true;
20672
21491
  }
20673
- const report = verifyMobilePublishReadiness(platform, env, createDefaultCommandProbe(spawnSync7));
21492
+ const report = verifyMobilePublishReadiness(platform, env, createDefaultCommandProbe(spawnSync8));
20674
21493
  writeLines(log, report.lines);
20675
21494
  return report.ok;
20676
21495
  };
@@ -20729,15 +21548,15 @@ var writeReportModeAssistant = (options) => {
20729
21548
  }
20730
21549
  };
20731
21550
  var runDoctor = async (log = console) => {
20732
- const platform = toPlatform(process19.platform);
21551
+ const platform = toPlatform(process21.platform);
20733
21552
  if (platform === null) {
20734
- log.error(`[doctor] This operating system (${process19.platform}) isn't supported yet.`);
21553
+ log.error(`[doctor] This operating system (${process21.platform}) isn't supported yet.`);
20735
21554
  return 1;
20736
21555
  }
20737
- const cwd = process19.cwd();
21556
+ const cwd = process21.cwd();
20738
21557
  const surface = inferProjectSurfaceSync(cwd);
20739
- const env = mergeEnv(process19.env, loadEnvFile2(cwd));
20740
- const cursorSession = isCursorSession();
21558
+ const env = mergeEnv(process21.env, loadEnvFile2(cwd));
21559
+ const cursorSession = isCursorSession2();
20741
21560
  if (cursorSession) {
20742
21561
  log.log("\u2713 Cursor - you're in Cursor; no separate agent install needed.");
20743
21562
  }
@@ -20777,13 +21596,57 @@ var runDoctor = async (log = console) => {
20777
21596
  });
20778
21597
  };
20779
21598
 
21599
+ // src/global/installState.ts
21600
+ import { mkdir as mkdir12, readFile as readFile20, writeFile as writeFile14 } from "fs/promises";
21601
+ import { join as join49 } from "path";
21602
+ var INSTALL_STATE_FILENAME = ".vybekiit-install.json";
21603
+ var installStatePath = (configDir) => join49(configDir, INSTALL_STATE_FILENAME);
21604
+ var readInstallState = async (configDir) => {
21605
+ try {
21606
+ const raw = await readFile20(installStatePath(configDir), "utf8");
21607
+ const parsed = JSON.parse(raw);
21608
+ if (typeof parsed.version !== "string" || parsed.version === "") {
21609
+ return null;
21610
+ }
21611
+ if (typeof parsed.updatedAt !== "string" || parsed.updatedAt === "") {
21612
+ return null;
21613
+ }
21614
+ const firstAppPath = typeof parsed.firstAppPath === "string" && parsed.firstAppPath !== "" ? parsed.firstAppPath : void 0;
21615
+ return {
21616
+ version: parsed.version,
21617
+ updatedAt: parsed.updatedAt,
21618
+ ...firstAppPath === void 0 ? {} : { firstAppPath }
21619
+ };
21620
+ } catch {
21621
+ return null;
21622
+ }
21623
+ };
21624
+ var writeInstallState = async (configDir, version, options = {}, now = () => /* @__PURE__ */ new Date()) => {
21625
+ const previous = await readInstallState(configDir);
21626
+ let firstAppPath = previous?.firstAppPath;
21627
+ if (options.clearFirstAppPath === true) {
21628
+ firstAppPath = void 0;
21629
+ } else if (options.firstAppPath !== void 0 && options.firstAppPath !== "") {
21630
+ firstAppPath = options.firstAppPath;
21631
+ }
21632
+ const state = {
21633
+ version,
21634
+ updatedAt: now().toISOString(),
21635
+ ...firstAppPath === void 0 ? {} : { firstAppPath }
21636
+ };
21637
+ await mkdir12(configDir, { recursive: true });
21638
+ await writeFile14(installStatePath(configDir), `${JSON.stringify(state, null, 2)}
21639
+ `, "utf8");
21640
+ return state;
21641
+ };
21642
+
20780
21643
  // src/global/runGlobalInstall.ts
20781
- import process21 from "process";
20782
- import { confirm, isCancel as isCancel2 } from "@clack/prompts";
21644
+ import process24 from "process";
21645
+ import { confirm as confirm2, isCancel as isCancel3 } from "@clack/prompts";
20783
21646
 
20784
21647
  // src/global/awareness.ts
20785
- import { mkdir as mkdir10, readFile as readFile17, writeFile as writeFile11 } from "fs/promises";
20786
- import { dirname as dirname15 } from "path";
21648
+ import { mkdir as mkdir13, readFile as readFile21, writeFile as writeFile15 } from "fs/promises";
21649
+ import { dirname as dirname16 } from "path";
20787
21650
  var BEGIN_MARKER = "<!-- BEGIN VYBEKIIT (managed by `vybekiit setup`) -->";
20788
21651
  var END_MARKER = "<!-- END VYBEKIIT -->";
20789
21652
  var LEADING_NEWLINE = /^\n/;
@@ -20796,8 +21659,10 @@ Do this now, briefly:
20796
21659
  1. Say: "\u2705 VybeKiit is active \u2014 you have its skills and browser automation in every project."
20797
21660
  2. Read the skill names under ~/.claude/skills and name 4-5 useful ones (for example: onboarding,
20798
21661
  plan-my-idea, setup-payments, add-signin, go-live).
20799
- 3. If there is no app in the current folder yet, offer to run \`vybekiit create app --web\`.
20800
- Otherwise ask what they want to build or change next.
21662
+ 3. If there is no app in the current folder yet, check for ~/vybekiit-app (first-install default).
21663
+ If it exists, offer to open that folder and run onboarding. Otherwise offer
21664
+ \`vybekiit create app --web\`. If they are already in an app folder, ask what they want next.
21665
+ 4. Mention Report mode once if they are in an app: Option+Shift+R (Alt+Shift+R on Windows).
20801
21666
 
20802
21667
  Keep it short and friendly. Do not dump the whole skill list.
20803
21668
  `;
@@ -20806,7 +21671,10 @@ var buildMemoryBlock = () => [
20806
21671
  "## VybeKiit is active on this machine",
20807
21672
  "",
20808
21673
  "VybeKiit is installed globally: its skills live in `~/.claude/skills`, and the `playwright`",
20809
- "and `context7` MCP servers are registered (browser automation + live library docs).",
21674
+ "and `context7` MCP servers are registered (browser automation, live library docs). Key-gated",
21675
+ "servers like `sentry`, `github`, and `stripe` register once their API key is set (run",
21676
+ "`vybekiit env wizard`). Inside a scaffolded app (`vybekiit create app`), a project-scoped",
21677
+ "`vybekiit` MCP server adds the kit tools (UI catalog, skills, browser automations).",
20810
21678
  "",
20811
21679
  "At the start of a session in any project, briefly tell the user VybeKiit is available, and use",
20812
21680
  "its skills (onboarding, plan-my-idea, setup-payments, add-signin, go-live, harden, \u2026) when they",
@@ -20831,7 +21699,7 @@ ${block}`;
20831
21699
  };
20832
21700
  var readOrEmpty = async (path) => {
20833
21701
  try {
20834
- return await readFile17(path, "utf8");
21702
+ return await readFile21(path, "utf8");
20835
21703
  } catch (error) {
20836
21704
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
20837
21705
  return "";
@@ -20843,8 +21711,8 @@ var writeIfChanged = async (path, next, previous) => {
20843
21711
  if (next === previous) {
20844
21712
  return false;
20845
21713
  }
20846
- await mkdir10(dirname15(path), { recursive: true });
20847
- await writeFile11(path, next, "utf8");
21714
+ await mkdir13(dirname16(path), { recursive: true });
21715
+ await writeFile15(path, next, "utf8");
20848
21716
  return true;
20849
21717
  };
20850
21718
  var STATUSLINE_BADGE = "\u25C6 vybekiit";
@@ -20903,20 +21771,20 @@ var installAwareness = async (paths) => {
20903
21771
  };
20904
21772
 
20905
21773
  // src/global/cliVersion.ts
20906
- import { readFile as readFile18 } from "fs/promises";
20907
- import { dirname as dirname16, join as join47 } from "path";
21774
+ import { readFile as readFile22 } from "fs/promises";
21775
+ import { dirname as dirname17, join as join50 } from "path";
20908
21776
  import { fileURLToPath as fileURLToPath8 } from "url";
20909
- var MODULE_DIR2 = dirname16(fileURLToPath8(import.meta.url));
21777
+ var MODULE_DIR2 = dirname17(fileURLToPath8(import.meta.url));
20910
21778
  var readCliVersion = async () => {
20911
21779
  const candidates = [
20912
21780
  // Published layout: dist/*.js → cli/package.json
20913
- join47(MODULE_DIR2, "..", "package.json"),
21781
+ join50(MODULE_DIR2, "..", "package.json"),
20914
21782
  // Source layout: src/global/*.ts → cli/package.json
20915
- join47(MODULE_DIR2, "..", "..", "package.json")
21783
+ join50(MODULE_DIR2, "..", "..", "package.json")
20916
21784
  ];
20917
21785
  for (const candidate of candidates) {
20918
21786
  try {
20919
- const raw = await readFile18(candidate, "utf8");
21787
+ const raw = await readFile22(candidate, "utf8");
20920
21788
  const parsed = JSON.parse(raw);
20921
21789
  if (parsed.version !== void 0 && parsed.version !== "") {
20922
21790
  return parsed.version;
@@ -21004,15 +21872,14 @@ var formatEntitlementBlock = (result) => {
21004
21872
  };
21005
21873
 
21006
21874
  // src/global/installGlobalMcp.ts
21007
- import process20 from "process";
21875
+ import process22 from "process";
21008
21876
  var ZERO_CONFIG = [
21009
21877
  {
21010
21878
  name: "playwright",
21011
21879
  transport: "stdio",
21012
- command: ["npx", "-y", "@anthropic-ai/mcp-playwright"]
21880
+ command: ["npx", "-y", "@playwright/mcp@latest"]
21013
21881
  },
21014
- { name: "context7", transport: "stdio", command: ["npx", "-y", "@upstash/context7-mcp@latest"] },
21015
- { name: "sentry", transport: "sse", command: ["https://mcp.sentry.dev/sse"] }
21882
+ { name: "context7", transport: "stdio", command: ["npx", "-y", "@upstash/context7-mcp@latest"] }
21016
21883
  ];
21017
21884
  var KEY_GATED = [
21018
21885
  {
@@ -21024,32 +21891,28 @@ var KEY_GATED = [
21024
21891
  {
21025
21892
  name: "supabase",
21026
21893
  transport: "stdio",
21027
- command: ["npx", "-y", "supabase-mcp-server"],
21894
+ command: ["npx", "-y", "@supabase/mcp-server-supabase@latest"],
21028
21895
  envKeys: ["SUPABASE_ACCESS_TOKEN"]
21029
21896
  },
21030
- {
21031
- name: "vercel",
21032
- transport: "stdio",
21033
- command: ["npx", "-y", "@vercel/mcp"],
21034
- envKeys: ["VERCEL_TOKEN"]
21035
- },
21036
21897
  {
21037
21898
  name: "stripe",
21038
21899
  transport: "stdio",
21039
- command: ["npx", "-y", "@stripe/mcp"],
21900
+ command: ["npx", "-y", "@stripe/mcp", "--tools=all"],
21040
21901
  envKeys: ["STRIPE_SECRET_KEY"]
21041
21902
  },
21042
21903
  {
21043
- name: "cloudflare",
21904
+ // Sentry's hosted server is OAuth-only (would sit "failed to connect" until the user
21905
+ // authenticates in a browser); its stdio server takes a token, so gate on that like the rest.
21906
+ name: "sentry",
21044
21907
  transport: "stdio",
21045
- command: ["npx", "-y", "@anthropic-ai/mcp-cloudflare"],
21046
- envKeys: ["CLOUDFLARE_API_TOKEN"]
21908
+ command: ["npx", "-y", "@sentry/mcp-server@latest"],
21909
+ envKeys: ["SENTRY_ACCESS_TOKEN"]
21047
21910
  },
21048
21911
  {
21049
21912
  name: "figma",
21050
21913
  transport: "stdio",
21051
- command: ["npx", "-y", "@anthropic-ai/mcp-figma"],
21052
- envKeys: ["FIGMA_ACCESS_TOKEN"]
21914
+ command: ["npx", "-y", "figma-developer-mcp", "--stdio"],
21915
+ envKeys: ["FIGMA_API_KEY"]
21053
21916
  },
21054
21917
  {
21055
21918
  name: "resend",
@@ -21076,7 +21939,7 @@ var KEY_GATED = [
21076
21939
  envKeys: ["TAVILY_API_KEY"]
21077
21940
  }
21078
21941
  ];
21079
- var defaultDeps2 = { exec: makeExec("claude"), env: process20.env };
21942
+ var defaultDeps2 = { exec: makeExec("claude"), env: process22.env };
21080
21943
  var buildAddArgs = (def, env) => {
21081
21944
  if (def.transport === "sse") {
21082
21945
  const [url = ""] = def.command;
@@ -21137,8 +22000,9 @@ var installGlobalMcp = async (deps = defaultDeps2) => {
21137
22000
  };
21138
22001
 
21139
22002
  // src/global/installGlobalSkills.ts
21140
- import { cp as cp5, mkdir as mkdir11, readdir as readdir9, readFile as readFile19, rm as rm5, stat as stat3, writeFile as writeFile12 } from "fs/promises";
21141
- import { join as join48 } from "path";
22003
+ import { cp as cp5, mkdir as mkdir14, readdir as readdir10, readFile as readFile23, rm as rm5, stat as stat3, writeFile as writeFile16 } from "fs/promises";
22004
+ import { join as join51 } from "path";
22005
+ var REQUIRED_MANAGED_SKILLS = ["feedback"];
21142
22006
  var pathExists8 = async (path) => {
21143
22007
  try {
21144
22008
  await stat3(path);
@@ -21149,14 +22013,14 @@ var pathExists8 = async (path) => {
21149
22013
  };
21150
22014
  var listBundledSkills = async (sourceDir) => {
21151
22015
  try {
21152
- const manifest = JSON.parse(await readFile19(join48(sourceDir, "manifest.json"), "utf8"));
22016
+ const manifest = JSON.parse(await readFile23(join51(sourceDir, "manifest.json"), "utf8"));
21153
22017
  if (Array.isArray(manifest.skills)) {
21154
22018
  return [...manifest.skills];
21155
22019
  }
21156
22020
  } catch {
21157
22021
  }
21158
22022
  try {
21159
- const entries = await readdir9(sourceDir, { withFileTypes: true });
22023
+ const entries = await readdir10(sourceDir, { withFileTypes: true });
21160
22024
  return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
21161
22025
  } catch {
21162
22026
  return [];
@@ -21164,54 +22028,285 @@ var listBundledSkills = async (sourceDir) => {
21164
22028
  };
21165
22029
  var installGlobalSkills = async (paths, sourceDir = paths.bundledSkillsDir) => {
21166
22030
  const names = await listBundledSkills(sourceDir);
21167
- await mkdir11(paths.skillsDir, { recursive: true });
22031
+ for (const requiredSkill of REQUIRED_MANAGED_SKILLS) {
22032
+ if (!names.includes(requiredSkill)) {
22033
+ throw new Error(`Bundled skills are incomplete: ${requiredSkill} is missing.`);
22034
+ }
22035
+ }
22036
+ await mkdir14(paths.skillsDir, { recursive: true });
21168
22037
  const installed = [];
21169
22038
  const skipped = [];
21170
22039
  for (const name of names) {
21171
- const dest = join48(paths.skillsDir, name);
22040
+ const dest = join51(paths.skillsDir, name);
21172
22041
  if (await pathExists8(dest)) {
21173
- if (!await pathExists8(join48(dest, MANAGED_SKILL_MARKER))) {
22042
+ if (!await pathExists8(join51(dest, MANAGED_SKILL_MARKER))) {
21174
22043
  skipped.push(name);
21175
22044
  continue;
21176
22045
  }
21177
22046
  await rm5(dest, { recursive: true, force: true });
21178
22047
  }
21179
- await cp5(join48(sourceDir, name), dest, { recursive: true });
21180
- await writeFile12(join48(dest, MANAGED_SKILL_MARKER), "", "utf8");
22048
+ await cp5(join51(sourceDir, name), dest, { recursive: true });
22049
+ await writeFile16(join51(dest, MANAGED_SKILL_MARKER), "", "utf8");
21181
22050
  installed.push(name);
21182
22051
  }
21183
22052
  return { installed, skipped, path: paths.skillsDir };
21184
22053
  };
21185
22054
 
21186
- // src/global/installState.ts
21187
- import { mkdir as mkdir12, readFile as readFile20, writeFile as writeFile13 } from "fs/promises";
21188
- import { join as join49 } from "path";
21189
- var INSTALL_STATE_FILENAME = ".vybekiit-install.json";
21190
- var installStatePath = (configDir) => join49(configDir, INSTALL_STATE_FILENAME);
21191
- var readInstallState = async (configDir) => {
22055
+ // src/global/runSessionOne.ts
22056
+ import { spawn as spawn2 } from "child_process";
22057
+ import { access as access15, readdir as readdir11 } from "fs/promises";
22058
+ import { homedir as homedir4 } from "os";
22059
+ import { join as join52 } from "path";
22060
+ import process23 from "process";
22061
+ var DEFAULT_FIRST_APP_DIR_NAME = "vybekiit-app";
22062
+ var SESSION_ONE_SEED_PROMPT = "Set up my app.";
22063
+ var shouldSkipSessionOne = (args, env = process23.env) => {
22064
+ if (args.includes("--skip-session-one") || args.includes("--skip-first-app")) {
22065
+ return true;
22066
+ }
22067
+ const flag = env.VYBEKIIT_SKIP_SESSION_ONE;
22068
+ return flag === "1" || flag === "true" || flag === "yes";
22069
+ };
22070
+ var resolveFirstAppPath = (deps) => {
22071
+ const override = deps.env.VYBEKIIT_FIRST_APP_DIR?.trim();
22072
+ if (override !== void 0 && override !== "") {
22073
+ return override.startsWith("/") || /^[A-Za-z]:[\\/]/.test(override) ? override : join52(deps.homeDir(), override);
22074
+ }
22075
+ return join52(deps.homeDir(), DEFAULT_FIRST_APP_DIR_NAME);
22076
+ };
22077
+ var defaultPathExists2 = async (path) => {
21192
22078
  try {
21193
- const raw = await readFile20(installStatePath(configDir), "utf8");
21194
- const parsed = JSON.parse(raw);
21195
- if (typeof parsed.version !== "string" || parsed.version === "") {
21196
- return null;
21197
- }
21198
- if (typeof parsed.updatedAt !== "string" || parsed.updatedAt === "") {
21199
- return null;
22079
+ await access15(path);
22080
+ return true;
22081
+ } catch {
22082
+ return false;
22083
+ }
22084
+ };
22085
+ var defaultIsEmptyDir = async (path) => {
22086
+ try {
22087
+ const entries = await readdir11(path);
22088
+ return entries.length === 0;
22089
+ } catch {
22090
+ return true;
22091
+ }
22092
+ };
22093
+ var defaultRunCommand = async (cwd, bin, args) => await new Promise((resolve13) => {
22094
+ const child = spawn2(bin, [...args], {
22095
+ cwd,
22096
+ stdio: ["ignore", "inherit", "inherit"],
22097
+ env: process23.env
22098
+ });
22099
+ child.on("error", () => {
22100
+ resolve13({ code: 127 });
22101
+ });
22102
+ child.on("close", (code) => {
22103
+ resolve13({ code: code ?? 1 });
22104
+ });
22105
+ });
22106
+ var defaultStartDetached = (cwd, bin, args) => {
22107
+ try {
22108
+ const child = spawn2(bin, [...args], {
22109
+ cwd,
22110
+ detached: true,
22111
+ stdio: "ignore",
22112
+ env: process23.env
22113
+ });
22114
+ child.unref();
22115
+ return true;
22116
+ } catch {
22117
+ return false;
22118
+ }
22119
+ };
22120
+ var openClaudeWithSeed = async (appPath, prompt, platform = process23.platform) => {
22121
+ if (platform === "darwin") {
22122
+ const shellCommand = `cd ${JSON.stringify(appPath)} && claude ${JSON.stringify(prompt)}`;
22123
+ const osa = makeExec("osascript");
22124
+ const result = await osa([
22125
+ "-e",
22126
+ `tell application "Terminal" to do script ${JSON.stringify(shellCommand)}`
22127
+ ]);
22128
+ if (result.code === 0) {
22129
+ return true;
21200
22130
  }
21201
- return { version: parsed.version, updatedAt: parsed.updatedAt };
22131
+ }
22132
+ try {
22133
+ const child = spawn2("claude", [prompt], {
22134
+ cwd: appPath,
22135
+ detached: true,
22136
+ stdio: "ignore",
22137
+ env: process23.env
22138
+ });
22139
+ child.unref();
22140
+ return true;
21202
22141
  } catch {
21203
- return null;
22142
+ return false;
21204
22143
  }
21205
22144
  };
21206
- var writeInstallState = async (configDir, version, now = () => /* @__PURE__ */ new Date()) => {
21207
- const state = {
21208
- version,
21209
- updatedAt: now().toISOString()
22145
+ var defaultResolvePnpm = async () => {
22146
+ const pnpm = makeExec("pnpm");
22147
+ const version = await pnpm(["--version"]);
22148
+ if (version.code === 0) {
22149
+ return ["pnpm"];
22150
+ }
22151
+ const corepack = makeExec("corepack");
22152
+ const enabled = await corepack(["enable"]);
22153
+ if (enabled.code === 0) {
22154
+ const prepared = await corepack(["prepare", "pnpm@10.33.2", "--activate"]);
22155
+ if (prepared.code === 0) {
22156
+ const again = await pnpm(["--version"]);
22157
+ if (again.code === 0) {
22158
+ return ["pnpm"];
22159
+ }
22160
+ }
22161
+ }
22162
+ const npx = makeExec("npx");
22163
+ const npxCheck = await npx(["-y", "pnpm@10.33.2", "--version"]);
22164
+ if (npxCheck.code === 0) {
22165
+ return ["npx", "-y", "pnpm@10.33.2"];
22166
+ }
22167
+ return null;
22168
+ };
22169
+ var defaultDeps3 = () => ({
22170
+ createApp: runCreateApp,
22171
+ pathExists: defaultPathExists2,
22172
+ isEmptyDir: defaultIsEmptyDir,
22173
+ runCommand: defaultRunCommand,
22174
+ startDetached: defaultStartDetached,
22175
+ openClaude: (appPath, prompt) => openClaudeWithSeed(appPath, prompt, process23.platform),
22176
+ resolvePnpm: defaultResolvePnpm,
22177
+ homeDir: homedir4,
22178
+ env: process23.env,
22179
+ platform: process23.platform
22180
+ });
22181
+ var formatSessionOneLines = (result) => {
22182
+ if (result.appPath === null) {
22183
+ return [
22184
+ "",
22185
+ "Session #1: could not create your first app automatically.",
22186
+ " Run: npx vybekiit create app --web",
22187
+ ' Then open that folder in Claude Code and say: "Set up my app."',
22188
+ ""
22189
+ ];
22190
+ }
22191
+ const lines = [
22192
+ "",
22193
+ result.created ? `\u2705 Your first web app is ready at ${result.appPath}` : `\u2705 Using your app at ${result.appPath}`
22194
+ ];
22195
+ if (result.depsInstalled) {
22196
+ lines.push(" \u2022 Dependencies installed");
22197
+ } else {
22198
+ lines.push(" \u2022 Dependencies still need install \u2014 in that folder run: pnpm install");
22199
+ }
22200
+ if (result.packagesBuilt) {
22201
+ lines.push(" \u2022 Kit packages built for local preview");
22202
+ } else if (result.depsInstalled) {
22203
+ lines.push(" \u2022 Kit packages still need a build \u2014 in that folder run: pnpm build:packages");
22204
+ }
22205
+ if (result.devStarted) {
22206
+ lines.push(" \u2022 Preview starting at http://localhost:3000");
22207
+ } else if (result.depsInstalled && result.packagesBuilt) {
22208
+ lines.push(" \u2022 Preview not started \u2014 in that folder run: pnpm dev");
22209
+ }
22210
+ if (result.claudeOpened) {
22211
+ lines.push(' \u2022 Claude Code opening with: "Set up my app."');
22212
+ } else {
22213
+ lines.push(' \u2022 Open Claude Code in that folder and say: "Set up my app."');
22214
+ lines.push(` cd ${result.appPath} && claude "Set up my app."`);
22215
+ }
22216
+ lines.push(
22217
+ "",
22218
+ "Report mode is built in \u2014 if something looks wrong, press Option+Shift+R",
22219
+ "(Alt+Shift+R on Windows), click it, and tell Claude what is off.",
22220
+ ""
22221
+ );
22222
+ return lines;
22223
+ };
22224
+ var runSessionOne = async (deps = defaultDeps3()) => {
22225
+ const appPath = resolveFirstAppPath(deps);
22226
+ const exists3 = await deps.pathExists(appPath);
22227
+ const empty = exists3 ? await deps.isEmptyDir(appPath) : true;
22228
+ let created = false;
22229
+ if (exists3 && !empty) {
22230
+ const looksLikeKit = await deps.pathExists(join52(appPath, "templates", "web"));
22231
+ if (!looksLikeKit) {
22232
+ const failed = {
22233
+ appPath: null,
22234
+ created: false,
22235
+ depsInstalled: false,
22236
+ packagesBuilt: false,
22237
+ devStarted: false,
22238
+ claudeOpened: false
22239
+ };
22240
+ return {
22241
+ ...failed,
22242
+ lines: [
22243
+ "",
22244
+ `Session #1: ${appPath} already exists and is not a VybeKiit app.`,
22245
+ " Pick a free folder and run: npx vybekiit create app --web ~/my-app",
22246
+ " Or set VYBEKIIT_FIRST_APP_DIR and re-run install once.",
22247
+ ""
22248
+ ]
22249
+ };
22250
+ }
22251
+ } else {
22252
+ process23.stdout.write(`
22253
+ Creating your first web app at ${appPath}\u2026
22254
+ `);
22255
+ const code = await deps.createApp(["--web", appPath]);
22256
+ if (code !== 0) {
22257
+ const failed = {
22258
+ appPath: null,
22259
+ created: false,
22260
+ depsInstalled: false,
22261
+ packagesBuilt: false,
22262
+ devStarted: false,
22263
+ claudeOpened: false
22264
+ };
22265
+ return { ...failed, lines: formatSessionOneLines(failed) };
22266
+ }
22267
+ created = true;
22268
+ }
22269
+ const pnpm = await deps.resolvePnpm();
22270
+ if (pnpm === null) {
22271
+ const partial = {
22272
+ appPath,
22273
+ created,
22274
+ depsInstalled: false,
22275
+ packagesBuilt: false,
22276
+ devStarted: false,
22277
+ claudeOpened: false
22278
+ };
22279
+ const claudeOpened2 = await deps.openClaude(appPath, SESSION_ONE_SEED_PROMPT);
22280
+ return {
22281
+ ...partial,
22282
+ claudeOpened: claudeOpened2,
22283
+ lines: formatSessionOneLines({ ...partial, claudeOpened: claudeOpened2 })
22284
+ };
22285
+ }
22286
+ const [pnpmBin, ...pnpmPrefix] = pnpm;
22287
+ process23.stdout.write("\nInstalling dependencies (this can take a few minutes)\u2026\n");
22288
+ const install = await deps.runCommand(appPath, pnpmBin, [...pnpmPrefix, "install"]);
22289
+ const depsInstalled = install.code === 0;
22290
+ let packagesBuilt = false;
22291
+ if (depsInstalled) {
22292
+ process23.stdout.write("\nBuilding kit packages for preview\u2026\n");
22293
+ const build = await deps.runCommand(appPath, pnpmBin, [...pnpmPrefix, "build:packages"]);
22294
+ packagesBuilt = build.code === 0;
22295
+ }
22296
+ let devStarted = false;
22297
+ if (depsInstalled && packagesBuilt) {
22298
+ devStarted = deps.startDetached(appPath, pnpmBin, [...pnpmPrefix, "dev"]);
22299
+ }
22300
+ const claudeOpened = await deps.openClaude(appPath, SESSION_ONE_SEED_PROMPT);
22301
+ const outcome = {
22302
+ appPath,
22303
+ created,
22304
+ depsInstalled,
22305
+ packagesBuilt,
22306
+ devStarted,
22307
+ claudeOpened
21210
22308
  };
21211
- await mkdir12(configDir, { recursive: true });
21212
- await writeFile13(installStatePath(configDir), `${JSON.stringify(state, null, 2)}
21213
- `, "utf8");
21214
- return state;
22309
+ return { ...outcome, lines: formatSessionOneLines(outcome) };
21215
22310
  };
21216
22311
 
21217
22312
  // src/global/runGlobalInstall.ts
@@ -21236,6 +22331,11 @@ var formatGlobalInstallSummary = (summary) => {
21236
22331
  if (summary.skillSample.length > 0) {
21237
22332
  lines.push(` smoke: ${summary.skillSample.join(", ")}`);
21238
22333
  }
22334
+ if (summary.skippedSkillNames.length > 0) {
22335
+ lines.push(
22336
+ ` kept your own same-named skills: ${summary.skippedSkillNames.join(", ")}`
22337
+ );
22338
+ }
21239
22339
  if (skillsEmpty) {
21240
22340
  lines.push(
21241
22341
  " No managed skills on disk \u2014 Claude Code will not load kit skills until this is fixed.",
@@ -21246,7 +22346,7 @@ var formatGlobalInstallSummary = (summary) => {
21246
22346
  lines.push(" \u2022 MCP skipped \u2014 the `claude` command was not found on your PATH");
21247
22347
  } else {
21248
22348
  const enabledLabel = summary.mcpEnabled.length > 0 ? summary.mcpEnabled.join(", ") : "none newly added";
21249
- lines.push(` \u2022 MCP ${enabledLabel} (browser automation + live docs everywhere)`);
22349
+ lines.push(` \u2022 MCP ${enabledLabel} (browser automation + live docs + error monitoring)`);
21250
22350
  if (summary.mcpRefreshed.length > 0) {
21251
22351
  lines.push(` refreshed: ${summary.mcpRefreshed.join(", ")}`);
21252
22352
  }
@@ -21260,7 +22360,7 @@ var formatGlobalInstallSummary = (summary) => {
21260
22360
  lines.push("");
21261
22361
  } else {
21262
22362
  lines.push(
21263
- " \u2022 Command type /vybekiit in Claude Code to see status anytime",
22363
+ summary.feedbackInstalled ? " \u2022 Command type /vybekiit for status or /feedback to send us a note" : " \u2022 Command type /vybekiit in Claude Code to see status anytime",
21264
22364
  " \u2022 Claude now knows it is VybeKiit-enabled in every project",
21265
22365
  "",
21266
22366
  "To see it: restart Claude Code (or run `claude` once) to approve the new MCP servers,",
@@ -21268,6 +22368,8 @@ var formatGlobalInstallSummary = (summary) => {
21268
22368
  "",
21269
22369
  "Re-run anytime to update: curl -fsSL https://vybekiit.com/install.sh | sh",
21270
22370
  " or: npx -y vybekiit@latest update",
22371
+ 'First install also creates your web app and opens Claude with "Set up my app."',
22372
+ "Skip that step: VYBEKIIT_SKIP_SESSION_ONE=1 or --skip-session-one",
21271
22373
  ""
21272
22374
  );
21273
22375
  }
@@ -21277,7 +22379,7 @@ var runGlobalInstall = async (args, gate = checkEntitlement) => {
21277
22379
  const entitlement = await gate();
21278
22380
  if (!entitlement.entitled) {
21279
22381
  for (const line of formatEntitlementBlock(entitlement)) {
21280
- process21.stderr.write(`${line}
22382
+ process24.stderr.write(`${line}
21281
22383
  `);
21282
22384
  }
21283
22385
  return 1;
@@ -21285,17 +22387,17 @@ var runGlobalInstall = async (args, gate = checkEntitlement) => {
21285
22387
  const skipPrompt = args.includes("--yes") || args.includes("-y");
21286
22388
  if (!skipPrompt) {
21287
22389
  if (!isInteractive()) {
21288
- process21.stdout.write(
22390
+ process24.stdout.write(
21289
22391
  "Skipping global setup (non-interactive). Run `vybekiit global-install --yes` or `vybekiit update` to provision Claude Code globally.\n"
21290
22392
  );
21291
22393
  return 0;
21292
22394
  }
21293
- const proceed = await confirm({
22395
+ const proceed = await confirm2({
21294
22396
  message: "Set up / update VybeKiit globally in Claude Code? Refreshes skills + browser automation in every project.",
21295
22397
  initialValue: true
21296
22398
  });
21297
- if (isCancel2(proceed) || proceed !== true) {
21298
- process21.stdout.write(
22399
+ if (isCancel3(proceed) || proceed !== true) {
22400
+ process24.stdout.write(
21299
22401
  "Skipped global setup. You can run `vybekiit update` or `vybekiit global-install` anytime.\n"
21300
22402
  );
21301
22403
  return 0;
@@ -21308,7 +22410,7 @@ var runGlobalInstall = async (args, gate = checkEntitlement) => {
21308
22410
  const skills = await installGlobalSkills(paths);
21309
22411
  const mcp = await installGlobalMcp({
21310
22412
  exec: makeExec("claude"),
21311
- env: process21.env,
22413
+ env: process24.env,
21312
22414
  forceRefresh: isRerun
21313
22415
  });
21314
22416
  const awareness = await installAwareness(paths);
@@ -21317,6 +22419,8 @@ var runGlobalInstall = async (args, gate = checkEntitlement) => {
21317
22419
  const summary = {
21318
22420
  skillsInstalled: skills.installed.length,
21319
22421
  skillsSkipped: skills.skipped.length,
22422
+ skippedSkillNames: skills.skipped,
22423
+ feedbackInstalled: skills.installed.includes("feedback"),
21320
22424
  skillSample,
21321
22425
  skillsPath: skills.path,
21322
22426
  mcpEnabled: mcp.enabled,
@@ -21328,24 +22432,38 @@ var runGlobalInstall = async (args, gate = checkEntitlement) => {
21328
22432
  previousVersion: previous?.version ?? null
21329
22433
  };
21330
22434
  for (const line of formatGlobalInstallSummary(summary)) {
21331
- process21.stdout.write(`${line}
22435
+ process24.stdout.write(`${line}
21332
22436
  `);
21333
22437
  }
21334
22438
  if (!isGloballyInstalled(postStatus)) {
21335
- process21.stderr.write(
22439
+ process24.stderr.write(
21336
22440
  "VybeKiit global install incomplete: expected managed skills + /vybekiit + CLAUDE.md block.\n"
21337
22441
  );
21338
22442
  return 1;
21339
22443
  }
21340
- await writeInstallState(paths.configDir, version);
22444
+ let firstAppPath = previous?.firstAppPath;
22445
+ const isFirstInstall = previous === null;
22446
+ if (isFirstInstall && !shouldSkipSessionOne(args)) {
22447
+ const sessionOne = await runSessionOne();
22448
+ for (const line of sessionOne.lines) {
22449
+ process24.stdout.write(`${line}
22450
+ `);
22451
+ }
22452
+ if (sessionOne.appPath !== null) {
22453
+ firstAppPath = sessionOne.appPath;
22454
+ }
22455
+ }
22456
+ await writeInstallState(paths.configDir, version, {
22457
+ ...firstAppPath === void 0 ? {} : { firstAppPath }
22458
+ });
21341
22459
  return 0;
21342
22460
  };
21343
22461
 
21344
22462
  // src/ui/welcomeBanner.ts
21345
- import process23 from "process";
22463
+ import process26 from "process";
21346
22464
 
21347
22465
  // src/ui/ansiShimmer.ts
21348
- import process22 from "process";
22466
+ import process25 from "process";
21349
22467
  var RESET = "\x1B[0m";
21350
22468
  var GRADIENT_START = [34, 211, 238];
21351
22469
  var GRADIENT_END = [167, 139, 250];
@@ -21357,7 +22475,7 @@ var colorAt = (t) => rgb(
21357
22475
  lerp(GRADIENT_START[1], GRADIENT_END[1], t),
21358
22476
  lerp(GRADIENT_START[2], GRADIENT_END[2], t)
21359
22477
  );
21360
- var supportsColor = (env = process22.env, isTTY = Boolean(process22.stdout.isTTY)) => {
22478
+ var supportsColor = (env = process25.env, isTTY = Boolean(process25.stdout.isTTY)) => {
21361
22479
  if (env.NO_COLOR !== void 0 && env.NO_COLOR !== "") {
21362
22480
  return false;
21363
22481
  }
@@ -21419,13 +22537,13 @@ var writeBlock = (write, lines) => {
21419
22537
  }
21420
22538
  };
21421
22539
  var playWelcomeBanner = async (options = {}) => {
21422
- const write = options.write === void 0 ? (text2) => process23.stdout.write(text2) : options.write;
22540
+ const write = options.write === void 0 ? (text2) => process26.stdout.write(text2) : options.write;
21423
22541
  const sleepFn = options.sleep === void 0 ? sleep : options.sleep;
21424
22542
  const frames = options.frames === void 0 ? DEFAULT_FRAMES : options.frames;
21425
22543
  const frameDelayMs = options.frameDelayMs === void 0 ? DEFAULT_FRAME_DELAY_MS : options.frameDelayMs;
21426
22544
  const art = [...WELCOME_ART];
21427
22545
  const useColor = !options.forcePlain && supportsColor();
21428
- const animate = useColor && Boolean(process23.stdout.isTTY) && frames > 0;
22546
+ const animate = useColor && Boolean(process26.stdout.isTTY) && frames > 0;
21429
22547
  if (!animate) {
21430
22548
  writeBlock(write, art);
21431
22549
  writeln(write, "");
@@ -21480,6 +22598,14 @@ var formatSetupNextStep = (input) => {
21480
22598
  ""
21481
22599
  ];
21482
22600
  }
22601
+ if (input.firstAppPath !== void 0 && input.firstAppPath !== "") {
22602
+ return [
22603
+ 'Your app is ready \u2014 open Claude Code in that folder and say: "Set up my app."',
22604
+ ` ${input.firstAppPath}`,
22605
+ " (If Claude is already open there, you are set.)",
22606
+ ""
22607
+ ];
22608
+ }
21483
22609
  return [
21484
22610
  "Next: create your app",
21485
22611
  " vybekiit create app --web",
@@ -21493,13 +22619,15 @@ var runSetup = async () => {
21493
22619
  await playWelcomeBanner();
21494
22620
  const code = await runDoctor();
21495
22621
  await runGlobalInstall(["--yes"]);
21496
- const access15 = checkAccess();
21497
- process24.stdout.write("\n");
22622
+ const access17 = checkAccess();
22623
+ const installState = await readInstallState(resolveGlobalPaths().configDir);
22624
+ process27.stdout.write("\n");
21498
22625
  for (const line of formatSetupNextStep({
21499
22626
  doctorExitCode: code,
21500
- gateReason: access15.reason
22627
+ gateReason: access17.reason,
22628
+ ...installState?.firstAppPath === void 0 ? {} : { firstAppPath: installState.firstAppPath }
21501
22629
  })) {
21502
- process24.stdout.write(`${line}
22630
+ process27.stdout.write(`${line}
21503
22631
  `);
21504
22632
  }
21505
22633
  return code;
@@ -21507,20 +22635,20 @@ var runSetup = async () => {
21507
22635
 
21508
22636
  // src/commands/syncAgentLayer.ts
21509
22637
  import { execFile as execFile7 } from "child_process";
21510
- import { access as access14, cp as cp6, readFile as readFile21, writeFile as writeFile14 } from "fs/promises";
21511
- import { join as join50 } from "path";
21512
- import process25 from "process";
22638
+ import { access as access16, cp as cp6, readFile as readFile24, writeFile as writeFile17 } from "fs/promises";
22639
+ import { join as join53 } from "path";
22640
+ import process28 from "process";
21513
22641
  import { promisify as promisify6 } from "util";
21514
22642
  var execFileAsync6 = promisify6(execFile7);
21515
- var defaultDeps3 = {
22643
+ var defaultDeps4 = {
21516
22644
  resolve: resolveTemplatesSource,
21517
22645
  copy: cp6,
21518
22646
  runSkillsUpdate: async (cwd) => {
21519
- await execFileAsync6("npx", ["skills", "update", "-y"], { cwd, env: process25.env });
22647
+ await execFileAsync6("npx", ["skills", "update", "-y"], { cwd, env: process28.env });
21520
22648
  },
21521
22649
  pathExists: async (path) => {
21522
22650
  try {
21523
- await access14(path);
22651
+ await access16(path);
21524
22652
  return true;
21525
22653
  } catch {
21526
22654
  return false;
@@ -21539,7 +22667,7 @@ var resolveSyncTemplate = async (explicit, cwd) => {
21539
22667
  var listMirrorAgentPaths = async (mirrorRoot, pathExists9) => {
21540
22668
  const entries = await Promise.all(
21541
22669
  AGENT_LAYER_PATHS.map(async (path) => {
21542
- if (await pathExists9(join50(mirrorRoot, path))) {
22670
+ if (await pathExists9(join53(mirrorRoot, path))) {
21543
22671
  return path;
21544
22672
  }
21545
22673
  return null;
@@ -21549,28 +22677,28 @@ var listMirrorAgentPaths = async (mirrorRoot, pathExists9) => {
21549
22677
  };
21550
22678
  var copyAgentLayerPath = async (options) => {
21551
22679
  const { mirrorRoot, cwd, path, copy, pathExists: pathExists9 } = options;
21552
- const src = join50(mirrorRoot, path);
21553
- const dest = join50(cwd, path);
22680
+ const src = join53(mirrorRoot, path);
22681
+ const dest = join53(cwd, path);
21554
22682
  if (path !== ".vybekiit") {
21555
22683
  await copy(src, dest, { recursive: true, force: true });
21556
22684
  return;
21557
22685
  }
21558
- const { readdir: readdir10, stat: stat4, mkdir: mkdir13 } = await import("fs/promises");
22686
+ const { readdir: readdir12, stat: stat4, mkdir: mkdir15 } = await import("fs/promises");
21559
22687
  const walk = async (rel) => {
21560
22688
  const relNorm = rel.split("\\").join("/");
21561
22689
  if (isAgentLayerExtensionPath(relNorm)) {
21562
22690
  return;
21563
22691
  }
21564
- const srcPath = join50(mirrorRoot, relNorm);
21565
- const destPath = join50(cwd, relNorm);
22692
+ const srcPath = join53(mirrorRoot, relNorm);
22693
+ const destPath = join53(cwd, relNorm);
21566
22694
  if (!await pathExists9(srcPath)) {
21567
22695
  return;
21568
22696
  }
21569
22697
  const info = await stat4(srcPath);
21570
22698
  if (info.isDirectory()) {
21571
- await mkdir13(destPath, { recursive: true });
21572
- const entries = await readdir10(srcPath);
21573
- await Promise.all(entries.map((entry) => walk(join50(relNorm, entry))));
22699
+ await mkdir15(destPath, { recursive: true });
22700
+ const entries = await readdir12(srcPath);
22701
+ await Promise.all(entries.map((entry) => walk(join53(relNorm, entry))));
21574
22702
  return;
21575
22703
  }
21576
22704
  await copy(srcPath, destPath, { force: true });
@@ -21594,21 +22722,21 @@ var readGoalIndexBeforeSync = async (pathsToSync, cwd, deps) => {
21594
22722
  if (!pathsToSync.includes(".vybekiit")) {
21595
22723
  return;
21596
22724
  }
21597
- const goalIndexPath = join50(cwd, ".vybekiit/agent/goal-index.md");
22725
+ const goalIndexPath = join53(cwd, ".vybekiit/agent/goal-index.md");
21598
22726
  if (!await deps.pathExists(goalIndexPath)) {
21599
22727
  return;
21600
22728
  }
21601
- return await readFile21(goalIndexPath, "utf8");
22729
+ return await readFile24(goalIndexPath, "utf8");
21602
22730
  };
21603
22731
  var mergeGoalIndexAfterSync = async (cwd, goalIndexBefore) => {
21604
22732
  if (goalIndexBefore === void 0) {
21605
22733
  return;
21606
22734
  }
21607
- const goalIndexPath = join50(cwd, ".vybekiit/agent/goal-index.md");
21608
- const synced = await readFile21(goalIndexPath, "utf8");
22735
+ const goalIndexPath = join53(cwd, ".vybekiit/agent/goal-index.md");
22736
+ const synced = await readFile24(goalIndexPath, "utf8");
21609
22737
  const merged = mergeGoalIndexOnSync(synced, goalIndexBefore);
21610
22738
  if (merged !== synced) {
21611
- await writeFile14(goalIndexPath, merged, "utf8");
22739
+ await writeFile17(goalIndexPath, merged, "utf8");
21612
22740
  }
21613
22741
  };
21614
22742
  var refreshGeneratedInstructionSections = async (cwd, template, deps) => {
@@ -21619,14 +22747,14 @@ var refreshGeneratedInstructionSections = async (cwd, template, deps) => {
21619
22747
  const rendered = applyAgentLayerSections(fileContents, { template });
21620
22748
  const writes = Object.entries(rendered).map(async ([file, content]) => {
21621
22749
  if (fileContents[file] !== void 0 && content !== fileContents[file]) {
21622
- await writeFile14(join50(cwd, file), content, "utf8");
22750
+ await writeFile17(join53(cwd, file), content, "utf8");
21623
22751
  }
21624
22752
  });
21625
22753
  await Promise.all(writes);
21626
22754
  return true;
21627
22755
  };
21628
22756
  var refreshPlatformInstructionFiles = async (cwd, deps) => {
21629
- if (!await deps.pathExists(join50(cwd, "skills-lock.json"))) {
22757
+ if (!await deps.pathExists(join53(cwd, "skills-lock.json"))) {
21630
22758
  return "missing-lock";
21631
22759
  }
21632
22760
  try {
@@ -21636,7 +22764,7 @@ var refreshPlatformInstructionFiles = async (cwd, deps) => {
21636
22764
  return "failed";
21637
22765
  }
21638
22766
  };
21639
- var runSyncAgentLayer = async (args, cwd = process25.cwd(), deps = defaultDeps3) => {
22767
+ var runSyncAgentLayer = async (args, cwd = process28.cwd(), deps = defaultDeps4) => {
21640
22768
  const [explicit] = args;
21641
22769
  const template = await resolveSyncTemplate(explicit, cwd);
21642
22770
  if (template === null) {
@@ -21655,7 +22783,7 @@ var runSyncAgentLayer = async (args, cwd = process25.cwd(), deps = defaultDeps3)
21655
22783
  });
21656
22784
  const { cleanup: resolvedCleanup, source } = resolved;
21657
22785
  cleanup = resolvedCleanup;
21658
- const mirrorRoot = join50(source, template);
22786
+ const mirrorRoot = join53(source, template);
21659
22787
  const mirrorPaths = await listMirrorAgentPaths(mirrorRoot, deps.pathExists);
21660
22788
  const plan = planAgentLayerSync(mirrorPaths);
21661
22789
  const lines = [formatAgentLayerSyncSummary(plan)];
@@ -21691,7 +22819,7 @@ var runSyncAgentLayer = async (args, cwd = process25.cwd(), deps = defaultDeps3)
21691
22819
  };
21692
22820
 
21693
22821
  // src/commands/updateKit.ts
21694
- import process26 from "process";
22822
+ import process29 from "process";
21695
22823
  import { Effect as Effect31 } from "effect";
21696
22824
  var runUpdateKit = async (args = []) => {
21697
22825
  const apply = args.includes("--apply");
@@ -21719,21 +22847,21 @@ var runUpdateKit = async (args = []) => {
21719
22847
  var runUpdateKitCommand = async (args) => {
21720
22848
  const result = await runUpdateKit(args);
21721
22849
  for (const line of result.lines) {
21722
- process26.stdout.write(`${line}
22850
+ process29.stdout.write(`${line}
21723
22851
  `);
21724
22852
  }
21725
22853
  return result.exitCode;
21726
22854
  };
21727
22855
 
21728
22856
  // src/doctor/ensureTool.ts
21729
- import { spawnSync as spawnSync8 } from "child_process";
21730
- import process27 from "process";
22857
+ import { spawnSync as spawnSync9 } from "child_process";
22858
+ import process30 from "process";
21731
22859
  var toPlatform2 = (platform) => platform === "darwin" || platform === "win32" || platform === "linux" ? platform : null;
21732
- var succeeds2 = (command, args) => spawnSync8(command, [...args], { stdio: "ignore" }).status === 0;
22860
+ var succeeds3 = (command, args) => spawnSync9(command, [...args], { stdio: "ignore" }).status === 0;
21733
22861
  var errorCode2 = (error) => error !== void 0 && "code" in error && typeof error.code === "string" ? error.code : void 0;
21734
22862
  var runInstall2 = (action, log) => {
21735
22863
  log.log(`[doctor] setting up ${action.tool}: ${action.command} ${action.args.join(" ")}`);
21736
- const result = spawnSync8(action.command, [...action.args], { stdio: "inherit" });
22864
+ const result = spawnSync9(action.command, [...action.args], { stdio: "inherit" });
21737
22865
  if (errorCode2(result.error) === "ENOENT") {
21738
22866
  return action.requires ? { ok: false, missingRequirement: action.requires } : { ok: false };
21739
22867
  }
@@ -21743,19 +22871,19 @@ var probeAuth = (tool) => {
21743
22871
  if (tool.auth === void 0) {
21744
22872
  return null;
21745
22873
  }
21746
- return succeeds2(tool.auth.command, tool.auth.args);
22874
+ return succeeds3(tool.auth.command, tool.auth.args);
21747
22875
  };
21748
22876
  var ensureTool = (name, log = console) => {
21749
22877
  const tool = findToolByName(name);
21750
22878
  if (tool === void 0) {
21751
22879
  return { tool: name, known: false, installed: false, installedNow: false, authed: null };
21752
22880
  }
21753
- const platform = toPlatform2(process27.platform);
22881
+ const platform = toPlatform2(process30.platform);
21754
22882
  if (!platform) {
21755
- log.error(`[doctor] This operating system (${process27.platform}) isn't supported yet.`);
22883
+ log.error(`[doctor] This operating system (${process30.platform}) isn't supported yet.`);
21756
22884
  return { tool: name, known: true, installed: false, installedNow: false, authed: null };
21757
22885
  }
21758
- const present = succeeds2(tool.name, tool.versionArgs);
22886
+ const present = succeeds3(tool.name, tool.versionArgs);
21759
22887
  const presence = [{ tool: tool.name, present }];
21760
22888
  let installedNow = false;
21761
22889
  let missingRequirement;
@@ -21796,9 +22924,9 @@ var formatEnsureResult = (result) => {
21796
22924
  };
21797
22925
 
21798
22926
  // src/prompts/envWizard.ts
21799
- import { readFile as readFile22 } from "fs/promises";
21800
- import { join as join51 } from "path";
21801
- import { cancel as cancel2, isCancel as isCancel3, text } from "@clack/prompts";
22927
+ import { readFile as readFile25 } from "fs/promises";
22928
+ import { join as join54 } from "path";
22929
+ import { cancel as cancel2, isCancel as isCancel4, text } from "@clack/prompts";
21802
22930
  var ENV_KEY_PATTERN = /^[A-Z][A-Z0-9_]*$/;
21803
22931
  var parseExampleEnvKeys = (raw) => raw.split("\n").reduce((keys, line) => {
21804
22932
  const separatorIndex = line.indexOf("=");
@@ -21849,19 +22977,19 @@ ${nextLine}
21849
22977
  `;
21850
22978
  };
21851
22979
  var runEnvWizard = async (cwd = process.cwd()) => {
21852
- const examplePath = join51(cwd, ".env.example");
22980
+ const examplePath = join54(cwd, ".env.example");
21853
22981
  let raw;
21854
22982
  try {
21855
- raw = await readFile22(examplePath, "utf8");
22983
+ raw = await readFile25(examplePath, "utf8");
21856
22984
  } catch {
21857
22985
  process.stderr.write("No .env.example in this folder.\n");
21858
22986
  return 1;
21859
22987
  }
21860
22988
  const keys = parseExampleEnvKeys(raw);
21861
- const envPath = join51(cwd, ".env");
22989
+ const envPath = join54(cwd, ".env");
21862
22990
  let envContent = "";
21863
22991
  try {
21864
- envContent = await readFile22(envPath, "utf8");
22992
+ envContent = await readFile25(envPath, "utf8");
21865
22993
  } catch {
21866
22994
  }
21867
22995
  for (const key of keys) {
@@ -21873,19 +23001,19 @@ var runEnvWizard = async (cwd = process.cwd()) => {
21873
23001
  defaultValue: current,
21874
23002
  placeholder: current
21875
23003
  });
21876
- if (isCancel3(value)) {
23004
+ if (isCancel4(value)) {
21877
23005
  cancel2("Cancelled.");
21878
23006
  return 1;
21879
23007
  }
21880
23008
  envContent = upsertEnvLine(envContent, key, value);
21881
23009
  }
21882
- const { writeFile: writeFile15 } = await import("fs/promises");
21883
- await writeFile15(envPath, envContent, "utf8");
23010
+ const { writeFile: writeFile18 } = await import("fs/promises");
23011
+ await writeFile18(envPath, envContent, "utf8");
21884
23012
  return 0;
21885
23013
  };
21886
23014
 
21887
23015
  // src/prompts/mainMenu.ts
21888
- import { cancel as cancel3, intro, isCancel as isCancel4, select as select2 } from "@clack/prompts";
23016
+ import { cancel as cancel3, intro, isCancel as isCancel5, select as select2 } from "@clack/prompts";
21889
23017
  var promptMainMenu = async () => {
21890
23018
  intro("Welcome to VybeKiit");
21891
23019
  const picked = await select2({
@@ -21918,7 +23046,7 @@ var promptMainMenu = async () => {
21918
23046
  }
21919
23047
  ]
21920
23048
  });
21921
- if (isCancel4(picked) || typeof picked !== "string") {
23049
+ if (isCancel5(picked) || typeof picked !== "string") {
21922
23050
  cancel3("Cancelled.");
21923
23051
  return null;
21924
23052
  }
@@ -21929,11 +23057,11 @@ var promptMainMenu = async () => {
21929
23057
  };
21930
23058
 
21931
23059
  // src/cliRunner.ts
21932
- var HERE7 = dirname17(fileURLToPath9(import.meta.url));
21933
- var GATE_EXEMPT = /* @__PURE__ */ new Set(["doctor", "setup", "global-install", "update"]);
23060
+ var HERE7 = dirname18(fileURLToPath9(import.meta.url));
23061
+ var GATE_EXEMPT = /* @__PURE__ */ new Set(["doctor", "setup", "global-install", "update", "feedback"]);
21934
23062
  var readVersion = async () => {
21935
23063
  try {
21936
- const raw = await readFile23(join52(HERE7, "..", "package.json"), "utf8");
23064
+ const raw = await readFile26(join55(HERE7, "..", "package.json"), "utf8");
21937
23065
  const parsed = JSON.parse(raw);
21938
23066
  if (parsed.version !== void 0 && parsed.version !== "") {
21939
23067
  return parsed.version;
@@ -21958,7 +23086,7 @@ var commandArgs = (context) => {
21958
23086
  };
21959
23087
  var writeLines2 = (lines) => {
21960
23088
  for (const line of lines) {
21961
- process28.stdout.write(`${line}
23089
+ process31.stdout.write(`${line}
21962
23090
  `);
21963
23091
  }
21964
23092
  };
@@ -21974,20 +23102,20 @@ var runDoctorEnsure = (toolName, json) => {
21974
23102
  if (toolName === void 0 || toolName === "" || toolName.startsWith("--")) {
21975
23103
  const message = "Usage: vybekiit doctor --ensure <tool> [--json]";
21976
23104
  if (json) {
21977
- process28.stdout.write(`${JSON.stringify({ ok: false, error: message })}
23105
+ process31.stdout.write(`${JSON.stringify({ ok: false, error: message })}
21978
23106
  `);
21979
23107
  } else {
21980
- process28.stderr.write(`${message}
23108
+ process31.stderr.write(`${message}
21981
23109
  `);
21982
23110
  }
21983
23111
  return 1;
21984
23112
  }
21985
23113
  const result = ensureTool(toolName);
21986
23114
  if (json) {
21987
- process28.stdout.write(`${JSON.stringify({ ok: result.installed, ...result })}
23115
+ process31.stdout.write(`${JSON.stringify({ ok: result.installed, ...result })}
21988
23116
  `);
21989
23117
  } else {
21990
- process28.stdout.write(`${formatEnsureResult(result)}
23118
+ process31.stdout.write(`${formatEnsureResult(result)}
21991
23119
  `);
21992
23120
  }
21993
23121
  return result.installed ? 0 : 1;
@@ -22003,47 +23131,47 @@ var handleDoctorCommand = async (context) => {
22003
23131
  var handleBackendCommand = async (context) => {
22004
23132
  if (context.subcommand === "add-route") {
22005
23133
  const result = await runBackendAddRoute([...context.rest]);
22006
- process28.stdout.write(`${result.message}
23134
+ process31.stdout.write(`${result.message}
22007
23135
  `);
22008
23136
  return result.exitCode;
22009
23137
  }
22010
23138
  if (context.subcommand === "add-crud") {
22011
23139
  const result = await runBackendAddCrud([...context.rest]);
22012
- process28.stdout.write(`${result.message}
23140
+ process31.stdout.write(`${result.message}
22013
23141
  `);
22014
23142
  return result.exitCode;
22015
23143
  }
22016
23144
  if (context.subcommand === "add-upload") {
22017
23145
  const result = await runBackendAddUpload();
22018
- process28.stdout.write(`${result.message}
23146
+ process31.stdout.write(`${result.message}
22019
23147
  `);
22020
23148
  return result.exitCode;
22021
23149
  }
22022
23150
  if (context.subcommand === "gen-contract") {
22023
23151
  const result = await runBackendGenContract();
22024
- process28.stdout.write(`${result.message}
23152
+ process31.stdout.write(`${result.message}
22025
23153
  `);
22026
23154
  return result.exitCode;
22027
23155
  }
22028
- process28.stderr.write(
23156
+ process31.stderr.write(
22029
23157
  "Unknown backend command. Try: backend add-route | add-crud | add-upload | gen-contract\n"
22030
23158
  );
22031
23159
  return 1;
22032
23160
  };
22033
23161
  var handleEnvCommand = async (context) => {
22034
23162
  if (context.subcommand !== "wizard") {
22035
- process28.stderr.write("Unknown env command. Try: vybekiit env wizard\n");
23163
+ process31.stderr.write("Unknown env command. Try: vybekiit env wizard\n");
22036
23164
  return 1;
22037
23165
  }
22038
23166
  if (!isInteractive()) {
22039
- process28.stderr.write("env wizard requires an interactive terminal.\n");
23167
+ process31.stderr.write("env wizard requires an interactive terminal.\n");
22040
23168
  return 1;
22041
23169
  }
22042
23170
  return await runEnvWizard();
22043
23171
  };
22044
23172
  var handleCreateCommand = async (context) => {
22045
23173
  if (context.subcommand !== "app") {
22046
- process28.stderr.write("Usage: vybekiit create app --web|--mobile|--extension [directory]\n");
23174
+ process31.stderr.write("Usage: vybekiit create app --web|--mobile|--extension [directory]\n");
22047
23175
  return 1;
22048
23176
  }
22049
23177
  return await runCreateApp([...context.rest]);
@@ -22051,7 +23179,7 @@ var handleCreateCommand = async (context) => {
22051
23179
  var wantsFullHelp = (argv) => argv.includes("--all") || argv.includes("-a");
22052
23180
  var runMainMenuChoice = async (choice) => {
22053
23181
  if (choice === "help-all") {
22054
- process28.stdout.write(`${CLI_HELP_ALL}
23182
+ process31.stdout.write(`${CLI_HELP_ALL}
22055
23183
  `);
22056
23184
  return 0;
22057
23185
  }
@@ -22078,18 +23206,24 @@ var handleAddCommand = async (context) => {
22078
23206
  }
22079
23207
  if (context.subcommand === "page-recipe") {
22080
23208
  const result = await runAddPageRecipe([...context.rest]);
22081
- process28.stdout.write(`${result.json}
23209
+ process31.stdout.write(`${result.json}
23210
+ `);
23211
+ return result.exitCode;
23212
+ }
23213
+ if (context.subcommand === "report-mode") {
23214
+ const result = await runAddReportMode([...context.rest]);
23215
+ process31.stdout.write(`${result.json}
22082
23216
  `);
22083
23217
  return result.exitCode;
22084
23218
  }
22085
23219
  if (context.subcommand === "preset") {
22086
23220
  const result = await runApplyPreset([...context.rest]);
22087
- process28.stdout.write(`${result.json}
23221
+ process31.stdout.write(`${result.json}
22088
23222
  `);
22089
23223
  return result.exitCode;
22090
23224
  }
22091
- process28.stderr.write(
22092
- "Unknown add command. Try: vybekiit add page-recipe <id> | add preset <id> | add bridge\n"
23225
+ process31.stderr.write(
23226
+ "Unknown add command. Try: vybekiit add page-recipe <id> | add report-mode | add preset <id> | add bridge\n"
22093
23227
  );
22094
23228
  return 1;
22095
23229
  };
@@ -22117,96 +23251,96 @@ var COMMAND_HANDLERS = {
22117
23251
  "render-agent-layer": async () => (await runRenderAgentLayer()).exitCode,
22118
23252
  "check-goals": async (context) => {
22119
23253
  const result = await runCheckGoals([...context.rest]);
22120
- process28.stdout.write(`${result.json}
23254
+ process31.stdout.write(`${result.json}
22121
23255
  `);
22122
23256
  return result.exitCode;
22123
23257
  },
22124
23258
  "check-agent-layer": async (context) => {
22125
23259
  const result = await runCheckAgentLayer([...context.rest]);
22126
- process28.stdout.write(`${result.json}
23260
+ process31.stdout.write(`${result.json}
22127
23261
  `);
22128
23262
  return result.exitCode;
22129
23263
  },
22130
23264
  "plan-readiness": async (context) => {
22131
23265
  const result = await runPlanReadiness([...context.rest]);
22132
- process28.stdout.write(`${result.json}
23266
+ process31.stdout.write(`${result.json}
22133
23267
  `);
22134
23268
  return result.exitCode;
22135
23269
  },
22136
23270
  "plan-setup": async (context) => {
22137
23271
  const result = await runPlanSetup([...context.rest]);
22138
- process28.stdout.write(`${result.output}
23272
+ process31.stdout.write(`${result.output}
22139
23273
  `);
22140
23274
  return result.exitCode;
22141
23275
  },
22142
23276
  "plan-data-model": async (context) => {
22143
23277
  const result = await runPlanDataModel([...context.rest]);
22144
- process28.stdout.write(`${result.json}
23278
+ process31.stdout.write(`${result.json}
22145
23279
  `);
22146
23280
  return result.exitCode;
22147
23281
  },
22148
23282
  "apply-preset": async (context) => {
22149
23283
  const result = await runApplyPreset(commandArgs(context));
22150
- process28.stdout.write(`${result.json}
23284
+ process31.stdout.write(`${result.json}
22151
23285
  `);
22152
23286
  return result.exitCode;
22153
23287
  },
22154
23288
  "list-presets": () => {
22155
23289
  const result = runListPresets();
22156
- process28.stdout.write(`${result.json}
23290
+ process31.stdout.write(`${result.json}
22157
23291
  `);
22158
23292
  return result.exitCode;
22159
23293
  },
22160
23294
  "list-pieces": async (context) => {
22161
23295
  const result = await runListPieces(commandArgs(context));
22162
- process28.stdout.write(`${result.json}
23296
+ process31.stdout.write(`${result.json}
22163
23297
  `);
22164
23298
  return result.exitCode;
22165
23299
  },
22166
23300
  "list-page-recipes": async (context) => {
22167
23301
  const result = await runListPageRecipes(commandArgs(context));
22168
- process28.stdout.write(`${result.json}
23302
+ process31.stdout.write(`${result.json}
22169
23303
  `);
22170
23304
  return result.exitCode;
22171
23305
  },
22172
23306
  "verify-presets": async (context) => {
22173
23307
  const result = await runVerifyPresets(commandArgs(context));
22174
- process28.stdout.write(`${result.json}
23308
+ process31.stdout.write(`${result.json}
22175
23309
  `);
22176
23310
  return result.exitCode;
22177
23311
  },
22178
23312
  "lint-extension-skill": async (context) => {
22179
23313
  const result = await runLintExtensionSkill([...context.rest]);
22180
- process28.stdout.write(`${result.json}
23314
+ process31.stdout.write(`${result.json}
22181
23315
  `);
22182
23316
  return result.exitCode;
22183
23317
  },
22184
23318
  "doc-fallback": (context) => {
22185
23319
  const result = runDocFallback([...context.rest]);
22186
- process28.stdout.write(`${result.json}
23320
+ process31.stdout.write(`${result.json}
22187
23321
  `);
22188
23322
  return result.exitCode;
22189
23323
  },
22190
23324
  "live-work": async (context) => {
22191
23325
  if (context.subcommand === "data") {
22192
23326
  const result = await runLiveWorkData([...context.rest]);
22193
- process28.stdout.write(`${result.json}
23327
+ process31.stdout.write(`${result.json}
22194
23328
  `);
22195
23329
  return result.exitCode;
22196
23330
  }
22197
23331
  if (context.subcommand === "host") {
22198
23332
  const result = await runLiveWorkHost([...context.rest]);
22199
- process28.stdout.write(`${result.json}
23333
+ process31.stdout.write(`${result.json}
22200
23334
  `);
22201
23335
  return result.exitCode;
22202
23336
  }
22203
23337
  if (context.subcommand === "payments") {
22204
23338
  const result = await runLiveWorkPayments([...context.rest]);
22205
- process28.stdout.write(`${result.json}
23339
+ process31.stdout.write(`${result.json}
22206
23340
  `);
22207
23341
  return result.exitCode;
22208
23342
  }
22209
- process28.stderr.write(
23343
+ process31.stderr.write(
22210
23344
  "Usage: vybekiit live-work data|host|payments [--mode=demo|dogfood|buyer] [--vendor=\u2026] [--cwd=dir] [--no-pin] [--fresh]\n"
22211
23345
  );
22212
23346
  return 1;
@@ -22214,7 +23348,7 @@ var COMMAND_HANDLERS = {
22214
23348
  dedup: async (context) => {
22215
23349
  const result = await runDedup(commandArgs(context));
22216
23350
  if (result.output !== "") {
22217
- process28.stdout.write(result.output);
23351
+ process31.stdout.write(result.output);
22218
23352
  }
22219
23353
  return result.exitCode;
22220
23354
  },
@@ -22222,15 +23356,16 @@ var COMMAND_HANDLERS = {
22222
23356
  env: handleEnvCommand,
22223
23357
  scaffold: async (context) => {
22224
23358
  if (context.subcommand !== "backend") {
22225
- process28.stderr.write("Unknown scaffold command. Try: vybekiit scaffold backend\n");
23359
+ process31.stderr.write("Unknown scaffold command. Try: vybekiit scaffold backend\n");
22226
23360
  return 1;
22227
23361
  }
22228
- const result = await runScaffoldBackend([...context.rest], process28.cwd());
22229
- process28.stdout.write(`${result.message}
23362
+ const result = await runScaffoldBackend([...context.rest], process31.cwd());
23363
+ process31.stdout.write(`${result.message}
22230
23364
  `);
22231
23365
  return result.exitCode;
22232
23366
  },
22233
- backend: handleBackendCommand
23367
+ backend: handleBackendCommand,
23368
+ feedback: (context) => runFeedback(commandArgs(context))
22234
23369
  };
22235
23370
  var COMMAND_NAMES = Object.keys(COMMAND_HANDLERS);
22236
23371
  var runCli = async (argv) => {
@@ -22243,17 +23378,17 @@ var runCli = async (argv) => {
22243
23378
  }
22244
23379
  return await runMainMenuChoice(choice);
22245
23380
  }
22246
- process28.stdout.write(`${CLI_HELP}
23381
+ process31.stdout.write(`${CLI_HELP}
22247
23382
  `);
22248
23383
  return 0;
22249
23384
  }
22250
23385
  if (context.command === "help" || context.command === "--help" || context.command === "-h") {
22251
- process28.stdout.write(`${wantsFullHelp(argv) ? CLI_HELP_ALL : CLI_HELP}
23386
+ process31.stdout.write(`${wantsFullHelp(argv) ? CLI_HELP_ALL : CLI_HELP}
22252
23387
  `);
22253
23388
  return 0;
22254
23389
  }
22255
23390
  if (context.command === "--version" || context.command === "-v") {
22256
- process28.stdout.write(`${await readVersion()}
23391
+ process31.stdout.write(`${await readVersion()}
22257
23392
  `);
22258
23393
  return 0;
22259
23394
  }
@@ -22262,7 +23397,7 @@ var runCli = async (argv) => {
22262
23397
  }
22263
23398
  const handler = COMMAND_HANDLERS[context.command];
22264
23399
  if (handler === void 0) {
22265
- process28.stderr.write(
23400
+ process31.stderr.write(
22266
23401
  `Unknown command: ${context.command}
22267
23402
  Try: vybekiit or vybekiit --help
22268
23403
  `
@@ -22274,9 +23409,9 @@ Try: vybekiit or vybekiit --help
22274
23409
 
22275
23410
  // src/bin.ts
22276
23411
  try {
22277
- process29.exit(await runCli(process29.argv.slice(2)));
23412
+ process32.exit(await runCli(process32.argv.slice(2)));
22278
23413
  } catch (error) {
22279
- process29.stderr.write(`vybekiit: ${caughtMessage(error)}
23414
+ process32.stderr.write(`vybekiit: ${caughtMessage(error)}
22280
23415
  `);
22281
- process29.exit(1);
23416
+ process32.exit(1);
22282
23417
  }