@holdyourvoice/hyv 2.9.12 → 2.9.13

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 (2) hide show
  1. package/dist/index.js +305 -298
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5943,7 +5943,7 @@ async function getAccessState() {
5943
5943
  try {
5944
5944
  const session = await checkSession();
5945
5945
  const plan = (session.plan || "none").toLowerCase();
5946
- const hasPaidPlan = session.valid && plan !== "none" && plan !== "free";
5946
+ const hasPaidPlan = session.valid && plan !== "none" && plan !== "free" && plan !== "expired" && plan !== "unknown";
5947
5947
  const state = {
5948
5948
  authenticated: session.valid,
5949
5949
  hasPaidPlan,
@@ -5979,7 +5979,8 @@ async function requirePaidFeature(feature) {
5979
5979
  throw new Error("can't reach the server. check your internet connection and try again.");
5980
5980
  }
5981
5981
  const plan = (data.plan || "none").toLowerCase();
5982
- if (!data.plan || plan === "none" || data.status === "none") {
5982
+ const subStatus = String(data.subscription_status || data.status || "").toLowerCase();
5983
+ if (!data.plan || plan === "none" || plan === "free" || plan === "expired" || subStatus === "trialing" || subStatus === "none") {
5983
5984
  throw new Error(FEATURE_MESSAGES[feature]);
5984
5985
  }
5985
5986
  }
@@ -5994,7 +5995,7 @@ async function maybeShowLimitedModeHint(hasProfile) {
5994
5995
  } else if (!access.authenticated) {
5995
5996
  console.log(import_chalk5.default.dim("\n local mode \u2014 free scan engine. profiles + learning: hyv init"));
5996
5997
  } else {
5997
- console.log(import_chalk5.default.dim("\n local mode \u2014 upgrade for full profiles + learning: hyv plan --upgrade"));
5998
+ console.log(import_chalk5.default.dim("\n local mode \u2014 upgrade for full profiles + learning: hyv upgrade"));
5998
5999
  }
5999
6000
  }
6000
6001
  function formatModeLabel(access, hasFullProfile) {
@@ -6017,10 +6018,10 @@ var init_access = __esm({
6017
6018
  init_auth();
6018
6019
  init_api();
6019
6020
  FEATURE_MESSAGES = {
6020
- profiles: "syncing voice profiles from your account requires a paid plan. run: hyv plan --upgrade",
6021
- learning: "the learning loop (reinforce, add) requires a paid plan. run: hyv plan --upgrade",
6022
- premiumPrompts: "rich profile-aware rewrite prompts require a paid plan. run: hyv plan --upgrade",
6023
- serverAnalysis: "server-assisted analysis requires a paid plan. run: hyv plan --upgrade"
6021
+ profiles: "syncing voice profiles from your account requires a paid plan. run: hyv upgrade",
6022
+ learning: "the learning loop (reinforce, add) requires a paid plan. run: hyv upgrade",
6023
+ premiumPrompts: "rich profile-aware rewrite prompts require a paid plan. run: hyv upgrade",
6024
+ serverAnalysis: "server-assisted analysis requires a paid plan. run: hyv upgrade"
6024
6025
  };
6025
6026
  localOnlyOverride = false;
6026
6027
  cachedAccess = null;
@@ -12136,6 +12137,54 @@ In conclusion, the key to success is to empower your team with actionable insigh
12136
12137
  }
12137
12138
  });
12138
12139
 
12140
+ // src/lib/billing-upgrade.ts
12141
+ var billing_upgrade_exports = {};
12142
+ __export(billing_upgrade_exports, {
12143
+ openBillingUpgrade: () => openBillingUpgrade
12144
+ });
12145
+ async function openBillingUpgrade(opts = {}) {
12146
+ const plan = opts.plan || "individual";
12147
+ const next = `/dashboard?tab=billing&checkout=${plan}`;
12148
+ const token = getToken();
12149
+ if (!token) {
12150
+ console.log(import_chalk14.default.cyan("\nSign in to upgrade \u2014 opening browser...\n"));
12151
+ try {
12152
+ await authenticateWithBrowser();
12153
+ } catch {
12154
+ console.log(import_chalk14.default.yellow("Sign-in cancelled or failed."));
12155
+ console.log(import_chalk14.default.dim(`Visit ${DASHBOARD_BILLING_URL} after running hyv init`));
12156
+ return;
12157
+ }
12158
+ }
12159
+ const access = await getAccessState();
12160
+ if (access.hasPaidPlan) {
12161
+ console.log(import_chalk14.default.green(`
12162
+ \u2713 You already have a paid plan (${access.plan}).`));
12163
+ console.log(import_chalk14.default.dim("Manage billing: hyv plan --manage\n"));
12164
+ return;
12165
+ }
12166
+ console.log(import_chalk14.default.cyan("\nOpening billing in your dashboard ($1 first month)...\n"));
12167
+ try {
12168
+ await openAuthenticatedDashboard({ next });
12169
+ console.log(import_chalk14.default.green("\n\u2713 Dashboard opened \u2014 pick a plan in billing"));
12170
+ console.log(import_chalk14.default.dim("Checkout opens automatically when you arrive from the CLI."));
12171
+ } catch {
12172
+ console.log(import_chalk14.default.yellow("Could not open dashboard automatically."));
12173
+ console.log(import_chalk14.default.dim(`Visit https://holdyourvoice.com${next} after hyv init`));
12174
+ }
12175
+ }
12176
+ var import_chalk14;
12177
+ var init_billing_upgrade = __esm({
12178
+ "src/lib/billing-upgrade.ts"() {
12179
+ "use strict";
12180
+ import_chalk14 = __toESM(require_source());
12181
+ init_access();
12182
+ init_config();
12183
+ init_auth();
12184
+ init_free_paid();
12185
+ }
12186
+ });
12187
+
12139
12188
  // node_modules/glob/dist/commonjs/index.min.js
12140
12189
  var require_index_min = __commonJS({
12141
12190
  "node_modules/glob/dist/commonjs/index.min.js"(exports2) {
@@ -15817,7 +15866,7 @@ function registerStatusCommand(program3) {
15817
15866
  if (latest && current !== "unknown" && compareSemver(current, latest) < 0) {
15818
15867
  console.log(import_chalk7.default.bold("\nUpdate"));
15819
15868
  console.log(import_chalk7.default.cyan(` ${current} \u2192 ${latest} available`));
15820
- console.log(import_chalk7.default.dim(" Run: hyv upgrade"));
15869
+ console.log(import_chalk7.default.dim(" Run: npm i -g @holdyourvoice/hyv@latest"));
15821
15870
  }
15822
15871
  console.log("");
15823
15872
  });
@@ -16913,7 +16962,7 @@ function generateLocalProfileFromStats(name, stats) {
16913
16962
  }
16914
16963
 
16915
16964
  // src/commands/plan.ts
16916
- var import_chalk14 = __toESM(require_source());
16965
+ var import_chalk15 = __toESM(require_source());
16917
16966
  init_config();
16918
16967
  init_auth();
16919
16968
  var import_open2 = __toESM(require_open());
@@ -16928,10 +16977,10 @@ function registerPlanCommand(program3) {
16928
16977
  }
16929
16978
  const token = getToken();
16930
16979
  if (!token) {
16931
- console.log(import_chalk14.default.yellow("\nNot authenticated \u2014 free tier still works.\n"));
16932
- console.log(import_chalk14.default.dim(" hyv scan draft.md | hyv welcome | npx @holdyourvoice/hyv scan draft.md"));
16980
+ console.log(import_chalk15.default.yellow("\nNot authenticated \u2014 free tier still works.\n"));
16981
+ console.log(import_chalk15.default.dim(" hyv scan draft.md | hyv welcome | npx @holdyourvoice/hyv scan draft.md"));
16933
16982
  printFreePaidMatrix({ compact: true });
16934
- console.log(import_chalk14.default.dim(" Run `hyv init` for profiles + learning.\n"));
16983
+ console.log(import_chalk15.default.dim(" Run `hyv init` for profiles + learning.\n"));
16935
16984
  return;
16936
16985
  }
16937
16986
  if (options.upgrade) {
@@ -16944,20 +16993,20 @@ function registerPlanCommand(program3) {
16944
16993
  await showPlan();
16945
16994
  }
16946
16995
  } catch (error) {
16947
- console.error(import_chalk14.default.red(`
16996
+ console.error(import_chalk15.default.red(`
16948
16997
  Error: ${error.message}`));
16949
16998
  process.exit(1);
16950
16999
  }
16951
17000
  });
16952
17001
  }
16953
17002
  async function showPlan() {
16954
- console.log(import_chalk14.default.bold("\nSubscription Plan\n"));
17003
+ console.log(import_chalk15.default.bold("\nSubscription Plan\n"));
16955
17004
  const response = await authenticatedRequest(
16956
17005
  cliApiUrl("/cli/heartbeat"),
16957
17006
  { method: "GET" }
16958
17007
  );
16959
17008
  if (response.status !== 200) {
16960
- console.log(import_chalk14.default.yellow("Could not fetch plan info."));
17009
+ console.log(import_chalk15.default.yellow("Could not fetch plan info."));
16961
17010
  return;
16962
17011
  }
16963
17012
  const data = response.data;
@@ -16975,39 +17024,31 @@ async function showPlan() {
16975
17024
  team: "$29/mo",
16976
17025
  agency: "Custom"
16977
17026
  };
16978
- console.log(import_chalk14.default.dim("Plan:"), import_chalk14.default.bold(planNames[plan] || plan));
16979
- console.log(import_chalk14.default.dim("Price:"), planPrices[plan] || "-");
16980
- console.log(import_chalk14.default.dim("Status:"), data.subscription_status || "none");
17027
+ console.log(import_chalk15.default.dim("Plan:"), import_chalk15.default.bold(planNames[plan] || plan));
17028
+ console.log(import_chalk15.default.dim("Price:"), planPrices[plan] || "-");
17029
+ console.log(import_chalk15.default.dim("Status:"), data.subscription_status || "none");
16981
17030
  if (license) {
16982
- console.log(import_chalk14.default.dim("License:"), license.key_hint);
17031
+ console.log(import_chalk15.default.dim("License:"), license.key_hint);
16983
17032
  }
16984
17033
  const access = await getAccessState();
16985
- console.log(import_chalk14.default.bold("\nFree tier (always)"));
16986
- console.log(import_chalk14.default.dim(" local scan, fix, check, mcp, all web tools \u2014 hyv welcome"));
17034
+ console.log(import_chalk15.default.bold("\nFree tier (always)"));
17035
+ console.log(import_chalk15.default.dim(" local scan, fix, check, mcp, all web tools \u2014 hyv welcome"));
16987
17036
  if (plan === "none" || !access.hasPaidPlan) {
16988
- console.log(import_chalk14.default.bold("\nUpgrade unlocks"));
16989
- console.log(import_chalk14.default.dim(" profiles, learning loop, hybrid analysis, rich rewrites"));
16990
- console.log(import_chalk14.default.dim(` ${PRICING_URL}`));
16991
- console.log(import_chalk14.default.dim("\n hyv plan --upgrade | hyv plan --free for full matrix"));
17037
+ console.log(import_chalk15.default.bold("\nUpgrade unlocks"));
17038
+ console.log(import_chalk15.default.dim(" profiles, learning loop, hybrid analysis, rich rewrites"));
17039
+ console.log(import_chalk15.default.dim(` ${PRICING_URL}`));
17040
+ console.log(import_chalk15.default.dim("\n hyv plan --upgrade | hyv plan --free for full matrix"));
16992
17041
  } else {
16993
17042
  console.log("\nManage your subscription:");
16994
- console.log(import_chalk14.default.dim(" hyv plan --manage"));
17043
+ console.log(import_chalk15.default.dim(" hyv plan --manage"));
16995
17044
  }
16996
17045
  }
16997
17046
  async function upgradePlan() {
16998
- console.log(import_chalk14.default.cyan("\nOpening billing in your dashboard ($1 first month)...\n"));
16999
- try {
17000
- await openAuthenticatedDashboard({ next: "/dashboard?tab=billing" });
17001
- console.log(import_chalk14.default.green("\n\u2713 Dashboard opened \u2014 you're already signed in"));
17002
- console.log(import_chalk14.default.dim("Pick a plan in billing. No second login."));
17003
- } catch {
17004
- console.log(import_chalk14.default.yellow("Could not open dashboard automatically."));
17005
- console.log(import_chalk14.default.dim(`Visit ${DASHBOARD_BILLING_URL} after running hyv init`));
17006
- console.log(import_chalk14.default.dim(`Or see plans: ${PRICING_URL}`));
17007
- }
17047
+ const { openBillingUpgrade: openBillingUpgrade2 } = await Promise.resolve().then(() => (init_billing_upgrade(), billing_upgrade_exports));
17048
+ await openBillingUpgrade2({ plan: "individual" });
17008
17049
  }
17009
17050
  async function openBillingPortal() {
17010
- console.log(import_chalk14.default.cyan("\nOpening billing portal...\n"));
17051
+ console.log(import_chalk15.default.cyan("\nOpening billing portal...\n"));
17011
17052
  const response = await authenticatedRequest(
17012
17053
  cliApiUrl("/cli/subscribe/manage"),
17013
17054
  { method: "POST" }
@@ -17016,41 +17057,41 @@ async function openBillingPortal() {
17016
17057
  const data = response.data;
17017
17058
  const portalUrl = data.portal_url;
17018
17059
  if (portalUrl) {
17019
- console.log(import_chalk14.default.dim("Opening browser..."));
17060
+ console.log(import_chalk15.default.dim("Opening browser..."));
17020
17061
  await (0, import_open2.default)(assertSafeOpenUrl(portalUrl));
17021
- console.log(import_chalk14.default.green("\n\u2713 Billing portal opened"));
17062
+ console.log(import_chalk15.default.green("\n\u2713 Billing portal opened"));
17022
17063
  } else {
17023
- console.log(import_chalk14.default.yellow("No portal URL received."));
17064
+ console.log(import_chalk15.default.yellow("No portal URL received."));
17024
17065
  }
17025
17066
  } else {
17026
- console.log(import_chalk14.default.yellow("Could not open billing portal."));
17027
- console.log(import_chalk14.default.dim(`Visit ${DASHBOARD_BILLING_URL} to manage billing.`));
17067
+ console.log(import_chalk15.default.yellow("Could not open billing portal."));
17068
+ console.log(import_chalk15.default.dim(`Visit ${DASHBOARD_BILLING_URL} to manage billing.`));
17028
17069
  }
17029
17070
  }
17030
17071
  async function downgradePlan() {
17031
- console.log(import_chalk14.default.yellow("\nDowngrade Plan\n"));
17072
+ console.log(import_chalk15.default.yellow("\nDowngrade Plan\n"));
17032
17073
  console.log("To downgrade your plan, please visit:");
17033
- console.log(import_chalk14.default.dim(` ${DASHBOARD_BILLING_URL}`));
17074
+ console.log(import_chalk15.default.dim(` ${DASHBOARD_BILLING_URL}`));
17034
17075
  console.log("\nOr contact support at shashank@holdyourvoice.com");
17035
17076
  }
17036
17077
 
17037
17078
  // src/commands/scan.ts
17038
- var import_chalk17 = __toESM(require_source());
17079
+ var import_chalk18 = __toESM(require_source());
17039
17080
  init_pipeline();
17040
17081
  init_local_profile();
17041
17082
  init_access();
17042
17083
 
17043
17084
  // src/lib/output.ts
17044
- var import_chalk15 = __toESM(require_source());
17085
+ var import_chalk16 = __toESM(require_source());
17045
17086
  var c = {
17046
- dim: (s) => import_chalk15.default.dim(s),
17047
- bold: (s) => import_chalk15.default.bold(s),
17048
- accent: (s) => import_chalk15.default.hex("#C4441A")(s),
17049
- green: (s) => import_chalk15.default.green(s),
17050
- red: (s) => import_chalk15.default.red(s),
17051
- yellow: (s) => import_chalk15.default.yellow(s),
17052
- cyan: (s) => import_chalk15.default.cyan(s),
17053
- white: (s) => import_chalk15.default.white(s)
17087
+ dim: (s) => import_chalk16.default.dim(s),
17088
+ bold: (s) => import_chalk16.default.bold(s),
17089
+ accent: (s) => import_chalk16.default.hex("#C4441A")(s),
17090
+ green: (s) => import_chalk16.default.green(s),
17091
+ red: (s) => import_chalk16.default.red(s),
17092
+ yellow: (s) => import_chalk16.default.yellow(s),
17093
+ cyan: (s) => import_chalk16.default.cyan(s),
17094
+ white: (s) => import_chalk16.default.white(s)
17054
17095
  };
17055
17096
  function logo() {
17056
17097
  return `${c.bold("hold your ")}${c.accent("voice")}`;
@@ -17198,7 +17239,7 @@ async function runHybridAnalysis(text, profile, opts = {}) {
17198
17239
  }
17199
17240
 
17200
17241
  // src/commands/history.ts
17201
- var import_chalk16 = __toESM(require_source());
17242
+ var import_chalk17 = __toESM(require_source());
17202
17243
  var fs17 = __toESM(require("fs"));
17203
17244
  var path16 = __toESM(require("path"));
17204
17245
  init_config();
@@ -17250,7 +17291,7 @@ function registerHistoryCommand(program3) {
17250
17291
  if (fs17.existsSync(HISTORY_FILE)) {
17251
17292
  fs17.unlinkSync(HISTORY_FILE);
17252
17293
  }
17253
- console.log(import_chalk16.default.green("\n\u2713 History cleared"));
17294
+ console.log(import_chalk17.default.green("\n\u2713 History cleared"));
17254
17295
  return;
17255
17296
  }
17256
17297
  let entries = readHistory();
@@ -17264,14 +17305,14 @@ function registerHistoryCommand(program3) {
17264
17305
  const limit = parseInt(options.limit, 10);
17265
17306
  entries = entries.slice(-limit);
17266
17307
  if (entries.length === 0) {
17267
- console.log(import_chalk16.default.dim("\nNo scan history yet. Run hyv scan or hyv score to start tracking."));
17308
+ console.log(import_chalk17.default.dim("\nNo scan history yet. Run hyv scan or hyv score to start tracking."));
17268
17309
  return;
17269
17310
  }
17270
17311
  if (options.format === "json") {
17271
17312
  console.log(JSON.stringify(entries, null, 2));
17272
17313
  return;
17273
17314
  }
17274
- console.log(import_chalk16.default.bold(`
17315
+ console.log(import_chalk17.default.bold(`
17275
17316
  score history (last ${entries.length} scans)
17276
17317
  `));
17277
17318
  if (options.chart) {
@@ -17283,7 +17324,7 @@ function registerHistoryCommand(program3) {
17283
17324
  if (min !== max) {
17284
17325
  console.log(` ${min} \u2524`);
17285
17326
  }
17286
- console.log(import_chalk16.default.dim(` \u2514${"\u2500".repeat(sl.length + 1)}`));
17327
+ console.log(import_chalk17.default.dim(` \u2514${"\u2500".repeat(sl.length + 1)}`));
17287
17328
  console.log("");
17288
17329
  }
17289
17330
  const scores = entries.map((e) => e.score);
@@ -17296,22 +17337,22 @@ function registerHistoryCommand(program3) {
17296
17337
  const firstAvg = firstHalf.reduce((s, e) => s + e.score, 0) / (firstHalf.length || 1);
17297
17338
  const secondAvg = secondHalf.reduce((s, e) => s + e.score, 0) / (secondHalf.length || 1);
17298
17339
  const trend = Math.round(secondAvg - firstAvg);
17299
- const trendStr = trend > 0 ? import_chalk16.default.green(`\u2191 improving (+${trend})`) : trend < 0 ? import_chalk16.default.red(`\u2193 declining (${trend})`) : import_chalk16.default.dim("\u2192 stable");
17300
- console.log(import_chalk16.default.dim(` avg: ${avg} best: ${best.score} worst: ${worst.score}`));
17301
- console.log(import_chalk16.default.dim(` trend: ${trendStr}`));
17302
- console.log(import_chalk16.default.bold("\n recent:\n"));
17340
+ const trendStr = trend > 0 ? import_chalk17.default.green(`\u2191 improving (+${trend})`) : trend < 0 ? import_chalk17.default.red(`\u2193 declining (${trend})`) : import_chalk17.default.dim("\u2192 stable");
17341
+ console.log(import_chalk17.default.dim(` avg: ${avg} best: ${best.score} worst: ${worst.score}`));
17342
+ console.log(import_chalk17.default.dim(` trend: ${trendStr}`));
17343
+ console.log(import_chalk17.default.bold("\n recent:\n"));
17303
17344
  const recent = entries.slice(-10).reverse();
17304
17345
  for (const entry of recent) {
17305
17346
  const time = new Date(entry.timestamp).toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit" });
17306
- const icon = entry.issues === 0 ? import_chalk16.default.green("\u2713") : import_chalk16.default.red("\u25CF");
17307
- const score = entry.score < 60 ? import_chalk16.default.red(`${entry.score}/100`) : entry.score < 80 ? import_chalk16.default.yellow(`${entry.score}/100`) : import_chalk16.default.green(`${entry.score}/100`);
17308
- const issues = entry.issues > 0 ? import_chalk16.default.red(`${entry.issues} issues`) : import_chalk16.default.dim("clean");
17347
+ const icon = entry.issues === 0 ? import_chalk17.default.green("\u2713") : import_chalk17.default.red("\u25CF");
17348
+ const score = entry.score < 60 ? import_chalk17.default.red(`${entry.score}/100`) : entry.score < 80 ? import_chalk17.default.yellow(`${entry.score}/100`) : import_chalk17.default.green(`${entry.score}/100`);
17349
+ const issues = entry.issues > 0 ? import_chalk17.default.red(`${entry.issues} issues`) : import_chalk17.default.dim("clean");
17309
17350
  const file = path16.basename(entry.file).slice(0, 25).padEnd(25);
17310
- console.log(` ${import_chalk16.default.dim(time)} ${icon} ${file} ${score} ${issues}`);
17351
+ console.log(` ${import_chalk17.default.dim(time)} ${icon} ${file} ${score} ${issues}`);
17311
17352
  }
17312
17353
  console.log("");
17313
17354
  } catch (error) {
17314
- console.error(import_chalk16.default.red(`Error: ${error.message}`));
17355
+ console.error(import_chalk17.default.red(`Error: ${error.message}`));
17315
17356
  process.exit(1);
17316
17357
  }
17317
17358
  });
@@ -17326,7 +17367,7 @@ function registerScanCommand(program3) {
17326
17367
  const profile = await loadProfileForCommand(options.profile);
17327
17368
  const { text, path: filePath } = readText(file);
17328
17369
  if (!text.trim()) {
17329
- console.warn(import_chalk17.default.yellow("File is empty or contains only whitespace."));
17370
+ console.warn(import_chalk18.default.yellow("File is empty or contains only whitespace."));
17330
17371
  process.exit(0);
17331
17372
  }
17332
17373
  const ignoreRules = options.ignore ? new Set(options.ignore.split(",").map((r) => r.trim())) : /* @__PURE__ */ new Set();
@@ -17369,26 +17410,26 @@ function registerScanCommand(program3) {
17369
17410
  }, null, 2));
17370
17411
  } else {
17371
17412
  if (signals.length === 0) {
17372
- console.log(import_chalk17.default.green(`
17413
+ console.log(import_chalk18.default.green(`
17373
17414
  \u2713 No issues found in ${filePath}`));
17374
- console.log(import_chalk17.default.dim(` score: ${score}/100`));
17415
+ console.log(import_chalk18.default.dim(` score: ${score}/100`));
17375
17416
  } else {
17376
- console.log(import_chalk17.default.bold(`
17417
+ console.log(import_chalk18.default.bold(`
17377
17418
  hyv scan ${filePath}`));
17378
17419
  if (profile) {
17379
- console.log(import_chalk17.default.dim(` profile: ${profile.slug || profile.name}${hasRichProfile(profile) ? " (full)" : ""}`));
17420
+ console.log(import_chalk18.default.dim(` profile: ${profile.slug || profile.name}${hasRichProfile(profile) ? " (full)" : ""}`));
17380
17421
  }
17381
17422
  if (analysis.message) {
17382
- console.log(import_chalk17.default.dim(` engine: ${analysis.message}`));
17423
+ console.log(import_chalk18.default.dim(` engine: ${analysis.message}`));
17383
17424
  }
17384
17425
  console.log("");
17385
17426
  printGroupedSignals(signals, profile);
17386
- console.log(import_chalk17.default.yellow(`
17427
+ console.log(import_chalk18.default.yellow(`
17387
17428
  ${signals.length} issues (${signals.filter((s) => s.severity === "red").length} red, ${signals.filter((s) => s.severity === "yellow").length} yellow)`));
17388
- console.log(import_chalk17.default.dim(` score: ${score}/100`));
17389
- console.log(import_chalk17.default.dim(`
17429
+ console.log(import_chalk18.default.dim(` score: ${score}/100`));
17430
+ console.log(import_chalk18.default.dim(`
17390
17431
  fix: hyv fix ${file}`));
17391
- console.log(import_chalk17.default.dim(` diff: hyv diff ${file}
17432
+ console.log(import_chalk18.default.dim(` diff: hyv diff ${file}
17392
17433
  `));
17393
17434
  }
17394
17435
  await maybeShowLimitedModeHint(!!profile);
@@ -17406,14 +17447,14 @@ hyv scan ${filePath}`));
17406
17447
  process.exit(2);
17407
17448
  }
17408
17449
  } catch (error) {
17409
- console.error(import_chalk17.default.red(`Error: ${error.message}`));
17450
+ console.error(import_chalk18.default.red(`Error: ${error.message}`));
17410
17451
  process.exit(1);
17411
17452
  }
17412
17453
  });
17413
17454
  }
17414
17455
 
17415
17456
  // src/commands/doctor.ts
17416
- var import_chalk18 = __toESM(require_source());
17457
+ var import_chalk19 = __toESM(require_source());
17417
17458
  var fs19 = __toESM(require("fs"));
17418
17459
  var path18 = __toESM(require("path"));
17419
17460
  var os9 = __toESM(require("os"));
@@ -17579,112 +17620,112 @@ function readMcpHyv(configFile) {
17579
17620
  }
17580
17621
  function registerDoctorCommand(program3) {
17581
17622
  program3.command("doctor").description("Diagnose CLI health: engine, cache, auth, agents").option("--fix-agents", "Re-run agent config copy (idempotent)").option("--verify-hosts", "Spawn MCP using each host config and report pass/fail").action(async (opts) => {
17582
- console.log(import_chalk18.default.bold("\nhold your voice \u2014 doctor\n"));
17623
+ console.log(import_chalk19.default.bold("\nhold your voice \u2014 doctor\n"));
17583
17624
  let issues = 0;
17584
17625
  let fixed = 0;
17585
- console.log(import_chalk18.default.dim(`engine: ${getEngineLabel()} (node ${process.version})`));
17626
+ console.log(import_chalk19.default.dim(`engine: ${getEngineLabel()} (node ${process.version})`));
17586
17627
  if (isLocalOnlyMode()) {
17587
- console.log(import_chalk18.default.yellow(" local-only mode: HYV_LOCAL_ONLY is set"));
17628
+ console.log(import_chalk19.default.yellow(" local-only mode: HYV_LOCAL_ONLY is set"));
17588
17629
  }
17589
17630
  const access = await getAccessState();
17590
17631
  const profile = await loadProfileForCommand();
17591
- console.log(import_chalk18.default.dim(`mode: ${formatModeLabel(access, hasRichProfile(profile))}`));
17592
- console.log(import_chalk18.default.dim("tip: run hyv welcome for free capabilities\n"));
17593
- console.log(import_chalk18.default.dim("checking cli installation..."));
17632
+ console.log(import_chalk19.default.dim(`mode: ${formatModeLabel(access, hasRichProfile(profile))}`));
17633
+ console.log(import_chalk19.default.dim("tip: run hyv welcome for free capabilities\n"));
17634
+ console.log(import_chalk19.default.dim("checking cli installation..."));
17594
17635
  const cliPath = process.argv[1];
17595
17636
  if (cliPath && fs19.existsSync(cliPath)) {
17596
- console.log(import_chalk18.default.green(" \u2713 cli installed"));
17637
+ console.log(import_chalk19.default.green(" \u2713 cli installed"));
17597
17638
  } else {
17598
- console.log(import_chalk18.default.red(" \u2717 cli not found"));
17639
+ console.log(import_chalk19.default.red(" \u2717 cli not found"));
17599
17640
  issues++;
17600
17641
  }
17601
- console.log(import_chalk18.default.dim("checking .hyv directory..."));
17642
+ console.log(import_chalk19.default.dim("checking .hyv directory..."));
17602
17643
  if (fs19.existsSync(HYV_DIR)) {
17603
- console.log(import_chalk18.default.green(" \u2713 .hyv directory exists"));
17644
+ console.log(import_chalk19.default.green(" \u2713 .hyv directory exists"));
17604
17645
  } else {
17605
- console.log(import_chalk18.default.yellow(" ! .hyv directory missing \u2014 creating..."));
17646
+ console.log(import_chalk19.default.yellow(" ! .hyv directory missing \u2014 creating..."));
17606
17647
  fs19.mkdirSync(HYV_DIR, { recursive: true, mode: 448 });
17607
17648
  fixed++;
17608
17649
  }
17609
- console.log(import_chalk18.default.dim("checking cache..."));
17650
+ console.log(import_chalk19.default.dim("checking cache..."));
17610
17651
  const diskProfiles = listDiskCachedProfiles();
17611
17652
  const syncMeta = path18.join(CACHE_DIR2, "sync-meta.json");
17612
17653
  if (diskProfiles.length > 0 || fs19.existsSync(syncMeta)) {
17613
- console.log(import_chalk18.default.green(` \u2713 profile cache (${diskProfiles.length} full profile(s))`));
17654
+ console.log(import_chalk19.default.green(` \u2713 profile cache (${diskProfiles.length} full profile(s))`));
17614
17655
  if (fs19.existsSync(syncMeta)) {
17615
17656
  try {
17616
17657
  const meta = JSON.parse(fs19.readFileSync(syncMeta, "utf-8"));
17617
- console.log(import_chalk18.default.dim(` last sync: ${meta.synced_at || "unknown"}`));
17658
+ console.log(import_chalk19.default.dim(` last sync: ${meta.synced_at || "unknown"}`));
17618
17659
  } catch {
17619
17660
  }
17620
17661
  }
17621
17662
  } else {
17622
- console.log(import_chalk18.default.dim(" - no full profile cache (free local engine still works)"));
17663
+ console.log(import_chalk19.default.dim(" - no full profile cache (free local engine still works)"));
17623
17664
  }
17624
- console.log(import_chalk18.default.dim("checking file permissions..."));
17665
+ console.log(import_chalk19.default.dim("checking file permissions..."));
17625
17666
  if (fs19.existsSync(HYV_DIR)) {
17626
17667
  const hyvMode = fs19.statSync(HYV_DIR).mode & 511;
17627
17668
  if ((hyvMode & 63) === 0) {
17628
- console.log(import_chalk18.default.green(" \u2713 .hyv directory permissions"));
17669
+ console.log(import_chalk19.default.green(" \u2713 .hyv directory permissions"));
17629
17670
  } else {
17630
- console.log(import_chalk18.default.yellow(" ! .hyv directory is world/group accessible"));
17631
- console.log(import_chalk18.default.dim(" run: chmod 700 ~/.hyv"));
17671
+ console.log(import_chalk19.default.yellow(" ! .hyv directory is world/group accessible"));
17672
+ console.log(import_chalk19.default.dim(" run: chmod 700 ~/.hyv"));
17632
17673
  issues++;
17633
17674
  }
17634
17675
  }
17635
17676
  if (fs19.existsSync(AUTH_FILE)) {
17636
17677
  if (isOwnerOnlyFile(AUTH_FILE)) {
17637
- console.log(import_chalk18.default.green(" \u2713 auth.json permissions"));
17678
+ console.log(import_chalk19.default.green(" \u2713 auth.json permissions"));
17638
17679
  } else {
17639
- console.log(import_chalk18.default.yellow(" ! auth.json is world/group readable"));
17640
- console.log(import_chalk18.default.dim(" run: chmod 600 ~/.hyv/auth.json"));
17680
+ console.log(import_chalk19.default.yellow(" ! auth.json is world/group readable"));
17681
+ console.log(import_chalk19.default.dim(" run: chmod 600 ~/.hyv/auth.json"));
17641
17682
  issues++;
17642
17683
  }
17643
17684
  }
17644
- console.log(import_chalk18.default.dim("checking authentication..."));
17685
+ console.log(import_chalk19.default.dim("checking authentication..."));
17645
17686
  if (isInitialized()) {
17646
17687
  const auth = readAuth();
17647
17688
  if (auth) {
17648
- console.log(import_chalk18.default.green(" \u2713 authenticated"));
17649
- console.log(import_chalk18.default.dim(` email: ${auth.user?.email || "unknown"}`));
17689
+ console.log(import_chalk19.default.green(" \u2713 authenticated"));
17690
+ console.log(import_chalk19.default.dim(` email: ${auth.user?.email || "unknown"}`));
17650
17691
  const session = await checkSession();
17651
17692
  if (session.valid) {
17652
- console.log(import_chalk18.default.green(" \u2713 session valid"));
17653
- console.log(import_chalk18.default.dim(` plan: ${session.plan || "none"}`));
17693
+ console.log(import_chalk19.default.green(" \u2713 session valid"));
17694
+ console.log(import_chalk19.default.dim(` plan: ${session.plan || "none"}`));
17654
17695
  } else {
17655
- console.log(import_chalk18.default.red(" \u2717 session expired"));
17656
- console.log(import_chalk18.default.dim(" run: hyv init"));
17696
+ console.log(import_chalk19.default.red(" \u2717 session expired"));
17697
+ console.log(import_chalk19.default.dim(" run: hyv init"));
17657
17698
  issues++;
17658
17699
  }
17659
17700
  } else {
17660
- console.log(import_chalk18.default.red(" \u2717 auth data missing"));
17701
+ console.log(import_chalk19.default.red(" \u2717 auth data missing"));
17661
17702
  issues++;
17662
17703
  }
17663
17704
  } else {
17664
- console.log(import_chalk18.default.yellow(" ! not authenticated (free local scan works)"));
17665
- console.log(import_chalk18.default.dim(" run: hyv init for profiles + learning"));
17705
+ console.log(import_chalk19.default.yellow(" ! not authenticated (free local scan works)"));
17706
+ console.log(import_chalk19.default.dim(" run: hyv init for profiles + learning"));
17666
17707
  }
17667
- console.log(import_chalk18.default.dim("checking voice profile..."));
17708
+ console.log(import_chalk19.default.dim("checking voice profile..."));
17668
17709
  const voiceMd = path18.join(HYV_DIR, "voice.md");
17669
17710
  const hasVoiceMd = fs19.existsSync(voiceMd) && fs19.readFileSync(voiceMd, "utf-8").trim().length > 50;
17670
17711
  const profileFiles = fs19.existsSync(PROFILES_DIR) ? fs19.readdirSync(PROFILES_DIR).filter((f) => f.endsWith(".md") && f !== "voice.md") : [];
17671
17712
  if (hasVoiceMd || profileFiles.length > 0 || diskProfiles.length > 0) {
17672
17713
  if (hasVoiceMd)
17673
- console.log(import_chalk18.default.green(" \u2713 voice.md exists"));
17714
+ console.log(import_chalk19.default.green(" \u2713 voice.md exists"));
17674
17715
  if (profileFiles.length > 0)
17675
- console.log(import_chalk18.default.green(` \u2713 ${profileFiles.length} markdown profile(s)`));
17716
+ console.log(import_chalk19.default.green(` \u2713 ${profileFiles.length} markdown profile(s)`));
17676
17717
  if (diskProfiles.length > 0)
17677
- console.log(import_chalk18.default.green(` \u2713 ${diskProfiles.length} full cached profile(s)`));
17718
+ console.log(import_chalk19.default.green(` \u2713 ${diskProfiles.length} full cached profile(s)`));
17678
17719
  } else {
17679
- console.log(import_chalk18.default.yellow(" ! no voice profile (optional for free scan)"));
17680
- console.log(import_chalk18.default.dim(" run: hyv new <name> or hyv init"));
17720
+ console.log(import_chalk19.default.yellow(" ! no voice profile (optional for free scan)"));
17721
+ console.log(import_chalk19.default.dim(" run: hyv new <name> or hyv init"));
17681
17722
  }
17682
- console.log(import_chalk18.default.dim("checking agent configurations..."));
17723
+ console.log(import_chalk19.default.dim("checking agent configurations..."));
17683
17724
  const cursorLegacyRule = path18.join(HOME, ".cursor", "rules", "hyv.md");
17684
17725
  const cursorRule = path18.join(HOME, ".cursor", "rules", "hyv.mdc");
17685
17726
  if (fs19.existsSync(cursorLegacyRule) && fs19.existsSync(cursorRule)) {
17686
- console.log(import_chalk18.default.yellow(" ! stale cursor rule ~/.cursor/rules/hyv.md (use hyv.mdc)"));
17687
- console.log(import_chalk18.default.dim(" run: rm ~/.cursor/rules/hyv.md (or hyv doctor --fix-agents)"));
17727
+ console.log(import_chalk19.default.yellow(" ! stale cursor rule ~/.cursor/rules/hyv.md (use hyv.mdc)"));
17728
+ console.log(import_chalk19.default.dim(" run: rm ~/.cursor/rules/hyv.md (or hyv doctor --fix-agents)"));
17688
17729
  issues++;
17689
17730
  }
17690
17731
  const agMcpFile = path18.join(HOME, ".gemini", "config", "mcp_config.json");
@@ -17704,9 +17745,9 @@ function registerDoctorCommand(program3) {
17704
17745
  ];
17705
17746
  for (const agent of agentChecks) {
17706
17747
  if (agent.ok) {
17707
- console.log(import_chalk18.default.green(` \u2713 ${agent.name}`));
17748
+ console.log(import_chalk19.default.green(` \u2713 ${agent.name}`));
17708
17749
  } else {
17709
- console.log(import_chalk18.default.dim(` - ${agent.name} not configured`));
17750
+ console.log(import_chalk19.default.dim(` - ${agent.name} not configured`));
17710
17751
  }
17711
17752
  }
17712
17753
  if (opts.fixAgents) {
@@ -17714,84 +17755,84 @@ function registerDoctorCommand(program3) {
17714
17755
  const pkgDir = path18.resolve(__dirname, "..");
17715
17756
  const { setupAgents } = require(path18.join(pkgDir, "scripts", "postinstall-lib.js"));
17716
17757
  const result = setupAgents({ pkgDir, quiet: true });
17717
- console.log(import_chalk18.default.green(` \u2713 re-ran agent setup (${result.configured.join(", ") || "no changes"})`));
17758
+ console.log(import_chalk19.default.green(` \u2713 re-ran agent setup (${result.configured.join(", ") || "no changes"})`));
17718
17759
  if (result.warnings.length) {
17719
- console.log(import_chalk18.default.yellow(` notes: ${result.warnings.join("; ")}`));
17760
+ console.log(import_chalk19.default.yellow(` notes: ${result.warnings.join("; ")}`));
17720
17761
  }
17721
17762
  fixed++;
17722
17763
  } catch (err) {
17723
- console.log(import_chalk18.default.yellow(` ! could not re-run agent setup: ${err.message}`));
17764
+ console.log(import_chalk19.default.yellow(` ! could not re-run agent setup: ${err.message}`));
17724
17765
  }
17725
17766
  }
17726
- console.log(import_chalk18.default.dim("checking mcp server..."));
17767
+ console.log(import_chalk19.default.dim("checking mcp server..."));
17727
17768
  const claudeMcp = readMcpHyv(path18.join(claudeDesktopDir(), "claude_desktop_config.json"));
17728
17769
  const cursorMcp = readMcpHyv(path18.join(HOME, ".cursor", "mcp.json"));
17729
17770
  if (claudeMcp || cursorMcp) {
17730
17771
  if (claudeMcp)
17731
- console.log(import_chalk18.default.green(" \u2713 mcp configured for claude desktop"));
17772
+ console.log(import_chalk19.default.green(" \u2713 mcp configured for claude desktop"));
17732
17773
  if (cursorMcp)
17733
- console.log(import_chalk18.default.green(" \u2713 mcp configured for cursor"));
17774
+ console.log(import_chalk19.default.green(" \u2713 mcp configured for cursor"));
17734
17775
  } else {
17735
- console.log(import_chalk18.default.yellow(" ! mcp not configured \u2014 run: hyv doctor --fix-agents or hyv mcp --setup"));
17776
+ console.log(import_chalk19.default.yellow(" ! mcp not configured \u2014 run: hyv doctor --fix-agents or hyv mcp --setup"));
17736
17777
  issues++;
17737
17778
  }
17738
17779
  try {
17739
17780
  const stdio = await testMcpStdioSubprocess();
17740
17781
  if (stdio.ok && (stdio.toolCount || 0) >= 10) {
17741
- console.log(import_chalk18.default.green(` \u2713 mcp stdio subprocess healthy (${stdio.toolCount} tools)`));
17782
+ console.log(import_chalk19.default.green(` \u2713 mcp stdio subprocess healthy (${stdio.toolCount} tools)`));
17742
17783
  } else if (stdio.ok) {
17743
- console.log(import_chalk18.default.yellow(` ! mcp stdio ok but only ${stdio.toolCount || 0} tools`));
17784
+ console.log(import_chalk19.default.yellow(` ! mcp stdio ok but only ${stdio.toolCount || 0} tools`));
17744
17785
  issues++;
17745
17786
  } else {
17746
- console.log(import_chalk18.default.red(" \u2717 mcp stdio subprocess failed"));
17747
- console.log(import_chalk18.default.dim(" run: hyv mcp --test"));
17787
+ console.log(import_chalk19.default.red(" \u2717 mcp stdio subprocess failed"));
17788
+ console.log(import_chalk19.default.dim(" run: hyv mcp --test"));
17748
17789
  issues++;
17749
17790
  }
17750
17791
  } catch (err) {
17751
- console.log(import_chalk18.default.red(` \u2717 mcp stdio probe failed: ${err.message}`));
17792
+ console.log(import_chalk19.default.red(` \u2717 mcp stdio probe failed: ${err.message}`));
17752
17793
  issues++;
17753
17794
  }
17754
17795
  if (opts.verifyHosts) {
17755
- console.log(import_chalk18.default.dim("verifying mcp hosts (spawns subprocess per config)..."));
17796
+ console.log(import_chalk19.default.dim("verifying mcp hosts (spawns subprocess per config)..."));
17756
17797
  try {
17757
17798
  const pkgDir = path18.resolve(__dirname, "..");
17758
17799
  const { verifyAgentHosts } = require(path18.join(pkgDir, "scripts", "verify-agent-hosts.js"));
17759
17800
  const hosts = await verifyAgentHosts();
17760
17801
  for (const host of hosts) {
17761
17802
  if (host.kind === "manual") {
17762
- console.log(import_chalk18.default.yellow(` \u25CB ${host.label} \u2014 ${host.detail}`));
17803
+ console.log(import_chalk19.default.yellow(` \u25CB ${host.label} \u2014 ${host.detail}`));
17763
17804
  continue;
17764
17805
  }
17765
17806
  if (host.ok) {
17766
- console.log(import_chalk18.default.green(` \u2713 ${host.label}${host.detail ? ` (${host.detail})` : ""}`));
17807
+ console.log(import_chalk19.default.green(` \u2713 ${host.label}${host.detail ? ` (${host.detail})` : ""}`));
17767
17808
  } else if (host.kind === "file") {
17768
- console.log(import_chalk18.default.dim(` - ${host.label} \u2014 ${host.detail || "missing"}`));
17809
+ console.log(import_chalk19.default.dim(` - ${host.label} \u2014 ${host.detail || "missing"}`));
17769
17810
  } else {
17770
- console.log(import_chalk18.default.red(` \u2717 ${host.label} \u2014 ${host.detail || "failed"}`));
17811
+ console.log(import_chalk19.default.red(` \u2717 ${host.label} \u2014 ${host.detail || "failed"}`));
17771
17812
  issues++;
17772
17813
  }
17773
17814
  }
17774
17815
  } catch (err) {
17775
- console.log(import_chalk18.default.red(` \u2717 host verification failed: ${err.message}`));
17816
+ console.log(import_chalk19.default.red(` \u2717 host verification failed: ${err.message}`));
17776
17817
  issues++;
17777
17818
  }
17778
17819
  }
17779
17820
  console.log("");
17780
17821
  if (issues === 0 && fixed === 0) {
17781
- console.log(import_chalk18.default.green("\u2713 everything looks good!"));
17822
+ console.log(import_chalk19.default.green("\u2713 everything looks good!"));
17782
17823
  } else if (fixed > 0) {
17783
- console.log(import_chalk18.default.green(`\u2713 fixed ${fixed} issue(s)`));
17824
+ console.log(import_chalk19.default.green(`\u2713 fixed ${fixed} issue(s)`));
17784
17825
  if (issues > 0)
17785
- console.log(import_chalk18.default.yellow(`! ${issues} issue(s) remaining`));
17826
+ console.log(import_chalk19.default.yellow(`! ${issues} issue(s) remaining`));
17786
17827
  } else {
17787
- console.log(import_chalk18.default.yellow(`! ${issues} issue(s) found`));
17828
+ console.log(import_chalk19.default.yellow(`! ${issues} issue(s) found`));
17788
17829
  }
17789
- console.log(import_chalk18.default.dim("\nfree scan: hyv scan draft.md | full tour: hyv welcome\n"));
17830
+ console.log(import_chalk19.default.dim("\nfree scan: hyv scan draft.md | full tour: hyv welcome\n"));
17790
17831
  });
17791
17832
  }
17792
17833
 
17793
17834
  // src/commands/rename.ts
17794
- var import_chalk19 = __toESM(require_source());
17835
+ var import_chalk20 = __toESM(require_source());
17795
17836
  init_config();
17796
17837
  init_auth();
17797
17838
  function registerRenameCommand(program3) {
@@ -17799,26 +17840,26 @@ function registerRenameCommand(program3) {
17799
17840
  try {
17800
17841
  const trimmedName = newName.trim();
17801
17842
  if (!trimmedName) {
17802
- console.log(import_chalk19.default.red("\nerror: what do you want to name your profile?\n"));
17803
- console.log(import_chalk19.default.dim(' example: hyv rename "my brand voice"\n'));
17843
+ console.log(import_chalk20.default.red("\nerror: what do you want to name your profile?\n"));
17844
+ console.log(import_chalk20.default.dim(' example: hyv rename "my brand voice"\n'));
17804
17845
  process.exit(1);
17805
17846
  return;
17806
17847
  }
17807
17848
  if (trimmedName.length > 100) {
17808
- console.log(import_chalk19.default.red("\nerror: name is too long \u2014 keep it under 100 characters\n"));
17849
+ console.log(import_chalk20.default.red("\nerror: name is too long \u2014 keep it under 100 characters\n"));
17809
17850
  process.exit(1);
17810
17851
  return;
17811
17852
  }
17812
17853
  if (!/^[a-zA-Z0-9\s\-_'&.]+$/.test(trimmedName)) {
17813
- console.log(import_chalk19.default.red("\nerror: name contains invalid characters\n"));
17814
- console.log(import_chalk19.default.dim(" allowed: letters, numbers, spaces, hyphens, underscores, apostrophes\n"));
17854
+ console.log(import_chalk20.default.red("\nerror: name contains invalid characters\n"));
17855
+ console.log(import_chalk20.default.dim(" allowed: letters, numbers, spaces, hyphens, underscores, apostrophes\n"));
17815
17856
  process.exit(1);
17816
17857
  return;
17817
17858
  }
17818
17859
  const token = getToken();
17819
17860
  if (!token) {
17820
- console.log(import_chalk19.default.red("\nerror: you're not signed in yet\n"));
17821
- console.log(import_chalk19.default.dim(" run: hyv init\n"));
17861
+ console.log(import_chalk20.default.red("\nerror: you're not signed in yet\n"));
17862
+ console.log(import_chalk20.default.dim(" run: hyv init\n"));
17822
17863
  process.exit(1);
17823
17864
  return;
17824
17865
  }
@@ -17834,16 +17875,16 @@ function registerRenameCommand(program3) {
17834
17875
  );
17835
17876
  if (response.status === 200) {
17836
17877
  const data = response.data;
17837
- console.log(import_chalk19.default.green(`
17878
+ console.log(import_chalk20.default.green(`
17838
17879
  \u2713 profile renamed to ${data.profile?.name || trimmedName}
17839
17880
  `));
17840
17881
  } else {
17841
- console.log(import_chalk19.default.red(`
17882
+ console.log(import_chalk20.default.red(`
17842
17883
  error: server returned ${response.status}
17843
17884
  `));
17844
17885
  }
17845
17886
  } catch (error) {
17846
- console.error(import_chalk19.default.red(`
17887
+ console.error(import_chalk20.default.red(`
17847
17888
  error: ${error.message}
17848
17889
  `));
17849
17890
  process.exit(1);
@@ -17852,7 +17893,7 @@ error: ${error.message}
17852
17893
  }
17853
17894
 
17854
17895
  // src/commands/fix.ts
17855
- var import_chalk21 = __toESM(require_source());
17896
+ var import_chalk22 = __toESM(require_source());
17856
17897
  init_pipeline();
17857
17898
  init_local_profile();
17858
17899
  init_access();
@@ -17862,14 +17903,14 @@ init_config();
17862
17903
  var fs20 = __toESM(require("fs"));
17863
17904
  var path19 = __toESM(require("path"));
17864
17905
  var readline2 = __toESM(require("readline"));
17865
- var import_chalk20 = __toESM(require_source());
17906
+ var import_chalk21 = __toESM(require_source());
17866
17907
  async function confirmDestructiveWrite(options) {
17867
17908
  if (options.yes)
17868
17909
  return true;
17869
17910
  const label = options.target ? `${options.action} (${options.target})` : options.action;
17870
17911
  if (!process.stdin.isTTY) {
17871
- console.error(import_chalk20.default.red("\nRefusing destructive write without confirmation (non-interactive)."));
17872
- console.error(import_chalk20.default.dim(" Re-run with --yes to create .bak backups and proceed.\n"));
17912
+ console.error(import_chalk21.default.red("\nRefusing destructive write without confirmation (non-interactive)."));
17913
+ console.error(import_chalk21.default.dim(" Re-run with --yes to create .bak backups and proceed.\n"));
17873
17914
  return false;
17874
17915
  }
17875
17916
  const question = `
@@ -17905,9 +17946,9 @@ function registerFixCommand(program3) {
17905
17946
  if (options.format === "json") {
17906
17947
  console.log(JSON.stringify({ file: filePath, autoFixes: 0, llmIssues: result.stats.needsLLM, changes: [] }));
17907
17948
  } else {
17908
- console.log(import_chalk21.default.green("\n\u2713 No auto-fixable issues found."));
17949
+ console.log(import_chalk22.default.green("\n\u2713 No auto-fixable issues found."));
17909
17950
  if (result.stats.needsLLM > 0) {
17910
- console.log(import_chalk21.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
17951
+ console.log(import_chalk22.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
17911
17952
  }
17912
17953
  }
17913
17954
  return;
@@ -17921,16 +17962,16 @@ function registerFixCommand(program3) {
17921
17962
  fixed: options.dryRun ? void 0 : result.fixed
17922
17963
  }, null, 2));
17923
17964
  } else {
17924
- console.log(import_chalk21.default.dim(`
17965
+ console.log(import_chalk22.default.dim(`
17925
17966
  hyv fix ${filePath}
17926
17967
  `));
17927
17968
  for (const change of result.changes) {
17928
- console.log(import_chalk21.default.dim(` Line ${change.line}: `) + import_chalk21.default.red(change.before) + import_chalk21.default.dim(" \u2192 ") + import_chalk21.default.green(change.after));
17969
+ console.log(import_chalk22.default.dim(` Line ${change.line}: `) + import_chalk22.default.red(change.before) + import_chalk22.default.dim(" \u2192 ") + import_chalk22.default.green(change.after));
17929
17970
  }
17930
- console.log(import_chalk21.default.green(`
17971
+ console.log(import_chalk22.default.green(`
17931
17972
  \u2713 ${result.changes.length} auto-fix${result.changes.length === 1 ? "" : "es"} applied`));
17932
17973
  if (result.stats.needsLLM > 0) {
17933
- console.log(import_chalk21.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
17974
+ console.log(import_chalk22.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
17934
17975
  }
17935
17976
  }
17936
17977
  if (!options.dryRun) {
@@ -17944,7 +17985,7 @@ hyv fix ${filePath}
17944
17985
  process.exit(1);
17945
17986
  }
17946
17987
  const backupPath = writeInPlaceWithBackup(filePath, result.fixed);
17947
- console.log(import_chalk21.default.dim(` Written to ${filePath} (backup: ${backupBasename(filePath)})`));
17988
+ console.log(import_chalk22.default.dim(` Written to ${filePath} (backup: ${backupBasename(filePath)})`));
17948
17989
  saveLastEditSession({
17949
17990
  original_path: filePath,
17950
17991
  edited_path: filePath,
@@ -17952,7 +17993,7 @@ hyv fix ${filePath}
17952
17993
  edited_text: result.fixed,
17953
17994
  profile: options.profile
17954
17995
  });
17955
- console.log(import_chalk21.default.dim(" Tip: hyv reinforce --last to teach your profile from this edit"));
17996
+ console.log(import_chalk22.default.dim(" Tip: hyv reinforce --last to teach your profile from this edit"));
17956
17997
  } else if (filePath === "stdin" || !options.inPlace) {
17957
17998
  process.stdout.write("\n" + result.fixed + "\n");
17958
17999
  if (filePath !== "stdin") {
@@ -17968,14 +18009,14 @@ hyv fix ${filePath}
17968
18009
  }
17969
18010
  await maybeShowLimitedModeHint(!!profile);
17970
18011
  } catch (error) {
17971
- console.error(import_chalk21.default.red(`Error: ${error.message}`));
18012
+ console.error(import_chalk22.default.red(`Error: ${error.message}`));
17972
18013
  process.exit(1);
17973
18014
  }
17974
18015
  });
17975
18016
  }
17976
18017
 
17977
18018
  // src/commands/check.ts
17978
- var import_chalk22 = __toESM(require_source());
18019
+ var import_chalk23 = __toESM(require_source());
17979
18020
  init_pipeline();
17980
18021
  init_local_profile();
17981
18022
  init_access();
@@ -17987,18 +18028,18 @@ function registerCheckCommand(program3) {
17987
18028
  if (text === "-") {
17988
18029
  const fs31 = require("fs");
17989
18030
  if (process.stdin.isTTY) {
17990
- console.error(import_chalk22.default.red("No input provided. Pipe content or pass text as argument."));
18031
+ console.error(import_chalk23.default.red("No input provided. Pipe content or pass text as argument."));
17991
18032
  process.exit(1);
17992
18033
  }
17993
18034
  inputText = fs31.readFileSync(0, "utf-8");
17994
18035
  }
17995
18036
  if (!inputText.trim()) {
17996
- console.error(import_chalk22.default.red("No text provided."));
18037
+ console.error(import_chalk23.default.red("No text provided."));
17997
18038
  process.exit(1);
17998
18039
  }
17999
18040
  const fs30 = require("fs");
18000
18041
  if (text !== "-" && fs30.existsSync(text)) {
18001
- console.log(import_chalk22.default.yellow(`"${text}" looks like a file. Did you mean: hyv scan ${text}`));
18042
+ console.log(import_chalk23.default.yellow(`"${text}" looks like a file. Did you mean: hyv scan ${text}`));
18002
18043
  process.exit(1);
18003
18044
  }
18004
18045
  const result = runPipeline(inputText, profile, false);
@@ -18022,30 +18063,30 @@ function registerCheckCommand(program3) {
18022
18063
  }, null, 2));
18023
18064
  } else {
18024
18065
  if (result.stats.totalSignals === 0) {
18025
- console.log(import_chalk22.default.green("\n\u2713 Clean \u2014 no AI patterns found."));
18026
- console.log(import_chalk22.default.dim(` score: ${result.score}/100`));
18066
+ console.log(import_chalk23.default.green("\n\u2713 Clean \u2014 no AI patterns found."));
18067
+ console.log(import_chalk23.default.dim(` score: ${result.score}/100`));
18027
18068
  } else {
18028
18069
  console.log("");
18029
18070
  printGroupedSignals(result.signalMap.signals.slice(0, 15), profile);
18030
18071
  if (result.signalMap.signals.length > 15) {
18031
- console.log(import_chalk22.default.dim(` ... and ${result.signalMap.signals.length - 15} more`));
18072
+ console.log(import_chalk23.default.dim(` ... and ${result.signalMap.signals.length - 15} more`));
18032
18073
  }
18033
- console.log(import_chalk22.default.yellow(`
18074
+ console.log(import_chalk23.default.yellow(`
18034
18075
  ${result.stats.totalSignals} issues (${result.stats.red} red, ${result.stats.yellow} yellow)`));
18035
- console.log(import_chalk22.default.dim(` score: ${result.score}/100`));
18076
+ console.log(import_chalk23.default.dim(` score: ${result.score}/100`));
18036
18077
  }
18037
18078
  await maybeShowLimitedModeHint(!!profile);
18038
18079
  }
18039
18080
  process.exit(result.stats.totalSignals > 0 ? 1 : 0);
18040
18081
  } catch (error) {
18041
- console.error(import_chalk22.default.red(`Error: ${error.message}`));
18082
+ console.error(import_chalk23.default.red(`Error: ${error.message}`));
18042
18083
  process.exit(1);
18043
18084
  }
18044
18085
  });
18045
18086
  }
18046
18087
 
18047
18088
  // src/commands/score.ts
18048
- var import_chalk23 = __toESM(require_source());
18089
+ var import_chalk24 = __toESM(require_source());
18049
18090
  init_pipeline();
18050
18091
  init_local_profile();
18051
18092
  function registerScoreCommand(program3) {
@@ -18070,14 +18111,14 @@ function registerScoreCommand(program3) {
18070
18111
  process.exit(1);
18071
18112
  }
18072
18113
  } catch (error) {
18073
- console.error(import_chalk23.default.red(`Error: ${error.message}`));
18114
+ console.error(import_chalk24.default.red(`Error: ${error.message}`));
18074
18115
  process.exit(1);
18075
18116
  }
18076
18117
  });
18077
18118
  }
18078
18119
 
18079
18120
  // src/commands/diff.ts
18080
- var import_chalk24 = __toESM(require_source());
18121
+ var import_chalk25 = __toESM(require_source());
18081
18122
  init_pipeline();
18082
18123
  init_local_profile();
18083
18124
  function registerDiffCommand(program3) {
@@ -18087,9 +18128,9 @@ function registerDiffCommand(program3) {
18087
18128
  const { text, path: filePath } = readText(file);
18088
18129
  const result = runPipeline(text, profile, true);
18089
18130
  if (result.changes.length === 0) {
18090
- console.log(import_chalk24.default.green("\n\u2713 No auto-fixable changes."));
18131
+ console.log(import_chalk25.default.green("\n\u2713 No auto-fixable changes."));
18091
18132
  if (result.stats.needsLLM > 0) {
18092
- console.log(import_chalk24.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite`));
18133
+ console.log(import_chalk25.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite`));
18093
18134
  }
18094
18135
  return;
18095
18136
  }
@@ -18104,42 +18145,42 @@ function registerDiffCommand(program3) {
18104
18145
  const originalLines = text.split("\n");
18105
18146
  const fixedLines = result.fixed.split("\n");
18106
18147
  const contextN = parseInt(options.context, 10);
18107
- console.log(import_chalk24.default.dim(`--- ${filePath}`));
18108
- console.log(import_chalk24.default.dim(`+++ ${filePath} (fixed)`));
18148
+ console.log(import_chalk25.default.dim(`--- ${filePath}`));
18149
+ console.log(import_chalk25.default.dim(`+++ ${filePath} (fixed)`));
18109
18150
  for (const change of result.changes) {
18110
18151
  const lineIdx = change.line - 1;
18111
18152
  const start = Math.max(0, lineIdx - contextN);
18112
18153
  const end = Math.min(originalLines.length, lineIdx + contextN + 1);
18113
- console.log(import_chalk24.default.dim(`@@ -${start + 1},${end - start} +${start + 1},${end - start} @@`));
18154
+ console.log(import_chalk25.default.dim(`@@ -${start + 1},${end - start} +${start + 1},${end - start} @@`));
18114
18155
  for (let i = start; i < end; i++) {
18115
18156
  if (i === lineIdx) {
18116
- console.log(import_chalk24.default.red(`-${originalLines[i]}`));
18117
- console.log(import_chalk24.default.green(`+${fixedLines[i]}`));
18157
+ console.log(import_chalk25.default.red(`-${originalLines[i]}`));
18158
+ console.log(import_chalk25.default.green(`+${fixedLines[i]}`));
18118
18159
  } else {
18119
- console.log(import_chalk24.default.dim(` ${originalLines[i]}`));
18160
+ console.log(import_chalk25.default.dim(` ${originalLines[i]}`));
18120
18161
  }
18121
18162
  }
18122
18163
  }
18123
- console.log(import_chalk24.default.green(`
18164
+ console.log(import_chalk25.default.green(`
18124
18165
  ${result.changes.length} auto-fix${result.changes.length === 1 ? "" : "es"} available`));
18125
- console.log(import_chalk24.default.dim(` run: hyv fix ${file} -i to apply`));
18166
+ console.log(import_chalk25.default.dim(` run: hyv fix ${file} -i to apply`));
18126
18167
  if (options.apply && filePath !== "stdin") {
18127
18168
  const fs30 = require("fs");
18128
18169
  const path27 = require("path");
18129
18170
  const backupPath = filePath + ".bak";
18130
18171
  fs30.copyFileSync(filePath, backupPath);
18131
18172
  fs30.writeFileSync(filePath, result.fixed);
18132
- console.log(import_chalk24.default.green(` \u2713 Applied. Backup: ${path27.basename(backupPath)}`));
18173
+ console.log(import_chalk25.default.green(` \u2713 Applied. Backup: ${path27.basename(backupPath)}`));
18133
18174
  }
18134
18175
  } catch (error) {
18135
- console.error(import_chalk24.default.red(`Error: ${error.message}`));
18176
+ console.error(import_chalk25.default.red(`Error: ${error.message}`));
18136
18177
  process.exit(1);
18137
18178
  }
18138
18179
  });
18139
18180
  }
18140
18181
 
18141
18182
  // src/commands/rules.ts
18142
- var import_chalk25 = __toESM(require_source());
18183
+ var import_chalk26 = __toESM(require_source());
18143
18184
  init_config();
18144
18185
  var RULE_CATALOG = [
18145
18186
  // AI Overused Words
@@ -18233,7 +18274,7 @@ function registerRulesCommand(program3) {
18233
18274
  for (const id of ids)
18234
18275
  disabledRules.delete(id);
18235
18276
  writeConfig({ ...config, disabled_rules: [...disabledRules] });
18236
- console.log(import_chalk25.default.green(`
18277
+ console.log(import_chalk26.default.green(`
18237
18278
  \u2713 Enabled: ${ids.join(", ")}`));
18238
18279
  return;
18239
18280
  }
@@ -18242,13 +18283,13 @@ function registerRulesCommand(program3) {
18242
18283
  for (const id of ids)
18243
18284
  disabledRules.add(id);
18244
18285
  writeConfig({ ...config, disabled_rules: [...disabledRules] });
18245
- console.log(import_chalk25.default.green(`
18286
+ console.log(import_chalk26.default.green(`
18246
18287
  \u2713 Disabled: ${ids.join(", ")}`));
18247
18288
  return;
18248
18289
  }
18249
18290
  if (options.reset) {
18250
18291
  writeConfig({ ...config, disabled_rules: [] });
18251
- console.log(import_chalk25.default.green("\n\u2713 All rules reset to default (enabled)"));
18292
+ console.log(import_chalk26.default.green("\n\u2713 All rules reset to default (enabled)"));
18252
18293
  return;
18253
18294
  }
18254
18295
  let rules = [...RULE_CATALOG];
@@ -18276,34 +18317,34 @@ function registerRulesCommand(program3) {
18276
18317
  }
18277
18318
  console.log("");
18278
18319
  for (const [cat, catRules] of categories) {
18279
- console.log(import_chalk25.default.bold(` ${cat} rules (${catRules.length})
18320
+ console.log(import_chalk26.default.bold(` ${cat} rules (${catRules.length})
18280
18321
  `));
18281
- console.log(import_chalk25.default.dim(" ID Sev AutoFix Status"));
18282
- console.log(import_chalk25.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
18322
+ console.log(import_chalk26.default.dim(" ID Sev AutoFix Status"));
18323
+ console.log(import_chalk26.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
18283
18324
  for (const rule of catRules) {
18284
- const sev = rule.severity === "red" ? import_chalk25.default.red("red") : import_chalk25.default.yellow("yel");
18285
- const fix = rule.autoFixable ? import_chalk25.default.green(" \u2713") : import_chalk25.default.dim(" \u2717");
18286
- const enabled2 = disabledRules.has(rule.id) ? import_chalk25.default.red(" \u2717 disabled") : import_chalk25.default.green(" \u2713 enabled");
18325
+ const sev = rule.severity === "red" ? import_chalk26.default.red("red") : import_chalk26.default.yellow("yel");
18326
+ const fix = rule.autoFixable ? import_chalk26.default.green(" \u2713") : import_chalk26.default.dim(" \u2717");
18327
+ const enabled2 = disabledRules.has(rule.id) ? import_chalk26.default.red(" \u2717 disabled") : import_chalk26.default.green(" \u2713 enabled");
18287
18328
  const id = rule.id.padEnd(24);
18288
- console.log(` ${import_chalk25.default.dim(id)} ${sev} ${fix} ${enabled2}`);
18329
+ console.log(` ${import_chalk26.default.dim(id)} ${sev} ${fix} ${enabled2}`);
18289
18330
  }
18290
18331
  console.log("");
18291
18332
  }
18292
18333
  const enabled = rules.filter((r) => !disabledRules.has(r.id)).length;
18293
18334
  const disabled = rules.length - enabled;
18294
- console.log(import_chalk25.default.dim(` ${rules.length} rules, ${enabled} enabled, ${disabled} disabled`));
18295
- console.log(import_chalk25.default.dim(` toggle: hyv rules --disable <id>`));
18296
- console.log(import_chalk25.default.dim(` reset: hyv rules --reset
18335
+ console.log(import_chalk26.default.dim(` ${rules.length} rules, ${enabled} enabled, ${disabled} disabled`));
18336
+ console.log(import_chalk26.default.dim(` toggle: hyv rules --disable <id>`));
18337
+ console.log(import_chalk26.default.dim(` reset: hyv rules --reset
18297
18338
  `));
18298
18339
  } catch (error) {
18299
- console.error(import_chalk25.default.red(`Error: ${error.message}`));
18340
+ console.error(import_chalk26.default.red(`Error: ${error.message}`));
18300
18341
  process.exit(1);
18301
18342
  }
18302
18343
  });
18303
18344
  }
18304
18345
 
18305
18346
  // src/commands/batch.ts
18306
- var import_chalk26 = __toESM(require_source());
18347
+ var import_chalk27 = __toESM(require_source());
18307
18348
  var fs21 = __toESM(require("fs"));
18308
18349
  var path20 = __toESM(require("path"));
18309
18350
  init_pipeline();
@@ -18318,7 +18359,7 @@ function registerBatchCommand(program3) {
18318
18359
  nodir: true
18319
18360
  });
18320
18361
  if (files.length === 0) {
18321
- console.log(import_chalk26.default.yellow(`
18362
+ console.log(import_chalk27.default.yellow(`
18322
18363
  No files matching: ${pattern}`));
18323
18364
  return;
18324
18365
  }
@@ -18332,7 +18373,7 @@ No files matching: ${pattern}`));
18332
18373
  process.exit(1);
18333
18374
  }
18334
18375
  if (options.format === "text") {
18335
- console.log(import_chalk26.default.dim(`
18376
+ console.log(import_chalk27.default.dim(`
18336
18377
  scanning ${files.length} file${files.length === 1 ? "" : "s"}...
18337
18378
  `));
18338
18379
  }
@@ -18371,23 +18412,23 @@ No files matching: ${pattern}`));
18371
18412
  }
18372
18413
  } else {
18373
18414
  for (const r of results) {
18374
- const icon = r.issues > 0 ? import_chalk26.default.red("\u25CF") : import_chalk26.default.green("\u25CB");
18375
- const score = r.score < 60 ? import_chalk26.default.red(r.score) : r.score < 80 ? import_chalk26.default.yellow(r.score) : import_chalk26.default.green(r.score);
18376
- const issueStr = r.issues > 0 ? import_chalk26.default.red(`${r.issues} issues`) : import_chalk26.default.green("clean");
18415
+ const icon = r.issues > 0 ? import_chalk27.default.red("\u25CF") : import_chalk27.default.green("\u25CB");
18416
+ const score = r.score < 60 ? import_chalk27.default.red(r.score) : r.score < 80 ? import_chalk27.default.yellow(r.score) : import_chalk27.default.green(r.score);
18417
+ const issueStr = r.issues > 0 ? import_chalk27.default.red(`${r.issues} issues`) : import_chalk27.default.green("clean");
18377
18418
  console.log(` ${icon} ${r.file.padEnd(40)} ${issueStr.padEnd(20)} score: ${score}`);
18378
18419
  }
18379
18420
  const withIssues = results.filter((r) => r.issues > 0).length;
18380
18421
  const totalIssues = results.reduce((sum, r) => sum + r.issues, 0);
18381
18422
  const worst = results.reduce((min, r) => r.score < min.score ? r : min, results[0]);
18382
- console.log(import_chalk26.default.dim(`
18423
+ console.log(import_chalk27.default.dim(`
18383
18424
  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
18384
- console.log(import_chalk26.default.dim(` ${results.length} files, ${withIssues} with issues, ${totalIssues} total issues`));
18425
+ console.log(import_chalk27.default.dim(` ${results.length} files, ${withIssues} with issues, ${totalIssues} total issues`));
18385
18426
  if (withIssues > 0) {
18386
- console.log(import_chalk26.default.dim(` worst: ${worst.file} (${worst.score}/100)`));
18427
+ console.log(import_chalk27.default.dim(` worst: ${worst.file} (${worst.score}/100)`));
18387
18428
  }
18388
18429
  if (options.fix && options.inPlace) {
18389
18430
  const fixed = results.filter((r) => r.autoFixes > 0);
18390
- console.log(import_chalk26.default.green(`
18431
+ console.log(import_chalk27.default.green(`
18391
18432
  \u2713 ${fixed.reduce((sum, r) => sum + r.autoFixes, 0)} auto-fixes applied across ${fixed.length} files`));
18392
18433
  }
18393
18434
  }
@@ -18399,14 +18440,14 @@ No files matching: ${pattern}`));
18399
18440
  if (belowThreshold)
18400
18441
  process.exit(1);
18401
18442
  } catch (error) {
18402
- console.error(import_chalk26.default.red(`Error: ${error.message}`));
18443
+ console.error(import_chalk27.default.red(`Error: ${error.message}`));
18403
18444
  process.exit(1);
18404
18445
  }
18405
18446
  });
18406
18447
  }
18407
18448
 
18408
18449
  // src/commands/watch.ts
18409
- var import_chalk27 = __toESM(require_source());
18450
+ var import_chalk28 = __toESM(require_source());
18410
18451
  var fs22 = __toESM(require("fs"));
18411
18452
  var path21 = __toESM(require("path"));
18412
18453
  init_pipeline();
@@ -18417,7 +18458,7 @@ function registerWatchCommand(program3) {
18417
18458
  const profile = await loadProfileForCommand(options.profile);
18418
18459
  const absPath = path21.resolve(file);
18419
18460
  if (!fs22.existsSync(absPath)) {
18420
- console.error(import_chalk27.default.red(`File not found: ${absPath}`));
18461
+ console.error(import_chalk28.default.red(`File not found: ${absPath}`));
18421
18462
  process.exit(1);
18422
18463
  }
18423
18464
  if (options.command === "fix") {
@@ -18429,10 +18470,10 @@ function registerWatchCommand(program3) {
18429
18470
  if (!confirmed)
18430
18471
  process.exit(1);
18431
18472
  }
18432
- console.log(import_chalk27.default.dim(`
18473
+ console.log(import_chalk28.default.dim(`
18433
18474
  watching ${absPath}`));
18434
- console.log(import_chalk27.default.dim(`command: ${options.command} debounce: ${options.debounce}ms`));
18435
- console.log(import_chalk27.default.dim("ctrl+c to stop\n"));
18475
+ console.log(import_chalk28.default.dim(`command: ${options.command} debounce: ${options.debounce}ms`));
18476
+ console.log(import_chalk28.default.dim("ctrl+c to stop\n"));
18436
18477
  let debounceTimer = null;
18437
18478
  const debounceMs = parseInt(options.debounce, 10);
18438
18479
  let scanCount = 0;
@@ -18443,38 +18484,38 @@ watching ${absPath}`));
18443
18484
  const result = runPipeline(text, profile, options.command === "fix");
18444
18485
  scanCount++;
18445
18486
  const now = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false });
18446
- console.log(import_chalk27.default.dim(`[${now}] saved \u2014 ${options.command}ing...`));
18487
+ console.log(import_chalk28.default.dim(`[${now}] saved \u2014 ${options.command}ing...`));
18447
18488
  if (options.command === "score") {
18448
18489
  const score = result.score;
18449
- const color = score < 60 ? import_chalk27.default.red : score < 80 ? import_chalk27.default.yellow : import_chalk27.default.green;
18490
+ const color = score < 60 ? import_chalk28.default.red : score < 80 ? import_chalk28.default.yellow : import_chalk28.default.green;
18450
18491
  console.log(` ${color(score + "/100")}`);
18451
18492
  if (lastScore > 0 && score !== lastScore) {
18452
18493
  const delta = score - lastScore;
18453
- console.log(import_chalk27.default.dim(` ${delta > 0 ? "\u2191" : "\u2193"} ${Math.abs(delta)} from last scan`));
18494
+ console.log(import_chalk28.default.dim(` ${delta > 0 ? "\u2191" : "\u2193"} ${Math.abs(delta)} from last scan`));
18454
18495
  }
18455
18496
  lastScore = score;
18456
18497
  } else if (options.command === "fix") {
18457
18498
  if (result.changes.length > 0) {
18458
18499
  for (const change of result.changes) {
18459
- console.log(import_chalk27.default.dim(` Line ${change.line}: `) + import_chalk27.default.red(change.before) + import_chalk27.default.dim(" \u2192 ") + import_chalk27.default.green(change.after));
18500
+ console.log(import_chalk28.default.dim(` Line ${change.line}: `) + import_chalk28.default.red(change.before) + import_chalk28.default.dim(" \u2192 ") + import_chalk28.default.green(change.after));
18460
18501
  }
18461
18502
  ignoreWatchUntil = Date.now() + debounceMs + 200;
18462
18503
  writeInPlaceWithBackup(absPath, result.fixed);
18463
- console.log(import_chalk27.default.green(` \u2713 ${result.changes.length} auto-fixes applied`));
18504
+ console.log(import_chalk28.default.green(` \u2713 ${result.changes.length} auto-fixes applied`));
18464
18505
  } else {
18465
- console.log(import_chalk27.default.green(" \u2713 no auto-fixable issues"));
18506
+ console.log(import_chalk28.default.green(" \u2713 no auto-fixable issues"));
18466
18507
  }
18467
18508
  } else {
18468
18509
  if (result.stats.totalSignals === 0) {
18469
- console.log(import_chalk27.default.green(` \u2713 clean \u2014 score: ${result.score}/100`));
18510
+ console.log(import_chalk28.default.green(` \u2713 clean \u2014 score: ${result.score}/100`));
18470
18511
  } else {
18471
- console.log(import_chalk27.default.yellow(` ${result.stats.totalSignals} issues (${result.stats.red} red, ${result.stats.yellow} yellow) score: ${result.score}/100`));
18512
+ console.log(import_chalk28.default.yellow(` ${result.stats.totalSignals} issues (${result.stats.red} red, ${result.stats.yellow} yellow) score: ${result.score}/100`));
18472
18513
  for (const signal of result.signalMap.signals.slice(0, 3)) {
18473
- const sev = signal.severity === "red" ? import_chalk27.default.red("\u25CF") : import_chalk27.default.yellow("\u25CB");
18514
+ const sev = signal.severity === "red" ? import_chalk28.default.red("\u25CF") : import_chalk28.default.yellow("\u25CB");
18474
18515
  console.log(` ${sev} line ${signal.line}: ${signal.id} \u2014 ${signal.suggestion}`);
18475
18516
  }
18476
18517
  if (result.signalMap.signals.length > 3) {
18477
- console.log(import_chalk27.default.dim(` ... and ${result.signalMap.signals.length - 3} more`));
18518
+ console.log(import_chalk28.default.dim(` ... and ${result.signalMap.signals.length - 3} more`));
18478
18519
  }
18479
18520
  }
18480
18521
  }
@@ -18491,21 +18532,21 @@ watching ${absPath}`));
18491
18532
  debounceTimer = setTimeout(runScan, debounceMs);
18492
18533
  });
18493
18534
  process.on("SIGINT", () => {
18494
- console.log(import_chalk27.default.dim(`
18535
+ console.log(import_chalk28.default.dim(`
18495
18536
  ${scanCount} scans completed. exiting.`));
18496
18537
  process.exit(0);
18497
18538
  });
18498
18539
  await new Promise(() => {
18499
18540
  });
18500
18541
  } catch (error) {
18501
- console.error(import_chalk27.default.red(`Error: ${error.message}`));
18542
+ console.error(import_chalk28.default.red(`Error: ${error.message}`));
18502
18543
  process.exit(1);
18503
18544
  }
18504
18545
  });
18505
18546
  }
18506
18547
 
18507
18548
  // src/commands/demo.ts
18508
- var import_chalk28 = __toESM(require_source());
18549
+ var import_chalk29 = __toESM(require_source());
18509
18550
  var fs23 = __toESM(require("fs"));
18510
18551
  var SAMPLES = {
18511
18552
  linkedin: {
@@ -18596,46 +18637,46 @@ function registerDemoCommand(program3) {
18596
18637
  const style = options.clean ? "clean" : options.style;
18597
18638
  const sample = SAMPLES[style];
18598
18639
  if (!sample) {
18599
- console.error(import_chalk28.default.red(`Unknown style: ${options.style}. Valid: ${Object.keys(SAMPLES).filter((k2) => k2 !== "clean").join(", ")}`));
18640
+ console.error(import_chalk29.default.red(`Unknown style: ${options.style}. Valid: ${Object.keys(SAMPLES).filter((k2) => k2 !== "clean").join(", ")}`));
18600
18641
  process.exit(1);
18601
18642
  }
18602
18643
  if (options.output) {
18603
18644
  const outputPath = require("path").resolve(options.output);
18604
18645
  fs23.writeFileSync(outputPath, sample.text);
18605
- console.log(import_chalk28.default.green(`
18646
+ console.log(import_chalk29.default.green(`
18606
18647
  \u2713 Sample written to ${outputPath}`));
18607
18648
  if (sample.patterns.length > 0) {
18608
- console.log(import_chalk28.default.dim(` Contains ${sample.patterns.length} AI patterns: ${sample.patterns.slice(0, 5).join(", ")}...`));
18649
+ console.log(import_chalk29.default.dim(` Contains ${sample.patterns.length} AI patterns: ${sample.patterns.slice(0, 5).join(", ")}...`));
18609
18650
  }
18610
- console.log(import_chalk28.default.dim(`
18651
+ console.log(import_chalk29.default.dim(`
18611
18652
  Scan it: hyv scan ${options.output}`));
18612
- console.log(import_chalk28.default.dim(` Fix it: hyv fix ${options.output}`));
18653
+ console.log(import_chalk29.default.dim(` Fix it: hyv fix ${options.output}`));
18613
18654
  } else {
18614
- console.log(import_chalk28.default.bold(`
18655
+ console.log(import_chalk29.default.bold(`
18615
18656
  \u2500\u2500\u2500 sample (${style}) \u2500\u2500\u2500
18616
18657
  `));
18617
18658
  console.log(sample.text);
18618
- console.log(import_chalk28.default.dim(`
18659
+ console.log(import_chalk29.default.dim(`
18619
18660
  \u2500\u2500\u2500 end \u2500\u2500\u2500`));
18620
18661
  if (sample.patterns.length > 0) {
18621
- console.log(import_chalk28.default.dim(`
18662
+ console.log(import_chalk29.default.dim(`
18622
18663
  ${sample.patterns.length} AI patterns embedded: ${sample.patterns.slice(0, 8).join(", ")}...`));
18623
18664
  }
18624
- console.log(import_chalk28.default.dim(`
18665
+ console.log(import_chalk29.default.dim(`
18625
18666
  Save to file: hyv demo --output demo.md`));
18626
- console.log(import_chalk28.default.dim(` Scan it: hyv scan demo.md`));
18627
- console.log(import_chalk28.default.dim(` Fix it: hyv fix demo.md
18667
+ console.log(import_chalk29.default.dim(` Scan it: hyv scan demo.md`));
18668
+ console.log(import_chalk29.default.dim(` Fix it: hyv fix demo.md
18628
18669
  `));
18629
18670
  }
18630
18671
  } catch (error) {
18631
- console.error(import_chalk28.default.red(`Error: ${error.message}`));
18672
+ console.error(import_chalk29.default.red(`Error: ${error.message}`));
18632
18673
  process.exit(1);
18633
18674
  }
18634
18675
  });
18635
18676
  }
18636
18677
 
18637
18678
  // src/commands/open.ts
18638
- var import_chalk29 = __toESM(require_source());
18679
+ var import_chalk30 = __toESM(require_source());
18639
18680
  var PAGES = {
18640
18681
  dashboard: "https://holdyourvoice.com/dashboard",
18641
18682
  profiles: "https://holdyourvoice.com/dashboard?tab=profiles",
@@ -18653,12 +18694,12 @@ function registerOpenCommand(program3) {
18653
18694
  return;
18654
18695
  }
18655
18696
  const open3 = (await Promise.resolve().then(() => __toESM(require_open()))).default;
18656
- console.log(import_chalk29.default.dim(`
18697
+ console.log(import_chalk30.default.dim(`
18657
18698
  Opening ${url}...`));
18658
18699
  await open3(url);
18659
- console.log(import_chalk29.default.green(" \u2713 Opened in browser\n"));
18700
+ console.log(import_chalk30.default.green(" \u2713 Opened in browser\n"));
18660
18701
  } catch (error) {
18661
- console.error(import_chalk29.default.red(`Error: ${error.message}`));
18702
+ console.error(import_chalk30.default.red(`Error: ${error.message}`));
18662
18703
  process.exit(1);
18663
18704
  }
18664
18705
  });
@@ -18744,7 +18785,7 @@ function getWelcomeText(args2) {
18744
18785
  }
18745
18786
 
18746
18787
  // src/commands/content.ts
18747
- var import_chalk30 = __toESM(require_source());
18788
+ var import_chalk31 = __toESM(require_source());
18748
18789
  init_free_paid();
18749
18790
  var TEMPLATES = {
18750
18791
  cursor: {
@@ -18818,62 +18859,28 @@ ${COMMUNITY_URL}`
18818
18859
  function registerContentCommand(program3) {
18819
18860
  program3.command("content").description("Blog outlines, CI snippets, and share templates").argument("[topic]", "cursor | agents | ci | share", "cursor").option("--list", "List available templates").action((topic, opts) => {
18820
18861
  if (opts.list) {
18821
- console.log(import_chalk30.default.bold("\nhyv content templates\n"));
18862
+ console.log(import_chalk31.default.bold("\nhyv content templates\n"));
18822
18863
  for (const [key, t2] of Object.entries(TEMPLATES)) {
18823
- console.log(import_chalk30.default.dim(` ${key}`) + ` \u2014 ${t2.title}`);
18864
+ console.log(import_chalk31.default.dim(` ${key}`) + ` \u2014 ${t2.title}`);
18824
18865
  }
18825
18866
  console.log("");
18826
18867
  return;
18827
18868
  }
18828
18869
  const t = TEMPLATES[topic] || TEMPLATES.cursor;
18829
- console.log(import_chalk30.default.bold(`
18870
+ console.log(import_chalk31.default.bold(`
18830
18871
  ${t.title}
18831
18872
  `));
18832
18873
  console.log(t.body);
18833
- console.log(import_chalk30.default.dim("\nBlog: https://holdyourvoice.com/blog\n"));
18874
+ console.log(import_chalk31.default.dim("\nBlog: https://holdyourvoice.com/blog\n"));
18834
18875
  });
18835
18876
  }
18836
18877
 
18837
18878
  // src/commands/upgrade.ts
18838
- var import_chalk31 = __toESM(require_source());
18839
- var import_child_process4 = require("child_process");
18840
- init_version();
18879
+ init_billing_upgrade();
18841
18880
  function registerUpgradeCommand(program3) {
18842
- program3.command("upgrade").description("Upgrade to the latest @holdyourvoice/hyv").option("--check", "Only check if an update is available").action(async (opts) => {
18843
- const current = getCliVersion();
18844
- console.log(import_chalk31.default.dim(`
18845
- Current: ${getEngineLabel()}
18846
- `));
18847
- let latest = current;
18848
- try {
18849
- const out = (0, import_child_process4.execSync)("npm view @holdyourvoice/hyv version", { encoding: "utf-8", timeout: 15e3 });
18850
- latest = out.trim();
18851
- } catch {
18852
- console.log(import_chalk31.default.yellow("Could not reach npm registry. Try: npm i -g @holdyourvoice/hyv@latest"));
18853
- return;
18854
- }
18855
- const cmp = compareSemver(current, latest);
18856
- if (cmp === 0) {
18857
- console.log(import_chalk31.default.green("\u2713 You are on the latest version."));
18858
- return;
18859
- }
18860
- if (cmp > 0) {
18861
- console.log(import_chalk31.default.green(`\u2713 You are ahead of npm (published: ${latest}).`));
18862
- return;
18863
- }
18864
- console.log(import_chalk31.default.cyan(`Update available: ${current} \u2192 ${latest}`));
18865
- if (opts.check) {
18866
- console.log(import_chalk31.default.dim("\nRun: hyv upgrade or npm i -g @holdyourvoice/hyv@latest\n"));
18867
- return;
18868
- }
18869
- console.log(import_chalk31.default.dim("Installing..."));
18870
- try {
18871
- (0, import_child_process4.execSync)("npm i -g @holdyourvoice/hyv@latest", { stdio: "inherit" });
18872
- console.log(import_chalk31.default.green("\n\u2713 Upgraded successfully. Restart your terminal.\n"));
18873
- } catch {
18874
- console.log(import_chalk31.default.red("\nUpgrade failed. Run manually: npm i -g @holdyourvoice/hyv@latest\n"));
18875
- process.exit(1);
18876
- }
18881
+ program3.command("upgrade").description("Upgrade to a paid plan (opens billing in your browser)").option("--plan <plan>", "Plan to checkout: individual or multiple", "individual").action(async (opts) => {
18882
+ const plan = opts.plan === "multiple" ? "multiple" : "individual";
18883
+ await openBillingUpgrade({ plan });
18877
18884
  });
18878
18885
  }
18879
18886