@holdyourvoice/hyv 2.9.12 → 2.9.14

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 +450 -342
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -5406,7 +5406,7 @@ var init_free_paid = __esm({
5406
5406
  ];
5407
5407
  COMMUNITY_URL = "https://holdyourvoice.com/community";
5408
5408
  PRICING_URL = "https://holdyourvoice.com/#pricing";
5409
- DASHBOARD_BILLING_URL = "https://holdyourvoice.com/dashboard?tab=billing";
5409
+ DASHBOARD_BILLING_URL = "https://holdyourvoice.com/app/billing";
5410
5410
  }
5411
5411
  });
5412
5412
 
@@ -5710,7 +5710,7 @@ async function authenticateWithBrowser() {
5710
5710
  return authData;
5711
5711
  }
5712
5712
  async function openAuthenticatedDashboard(opts = {}) {
5713
- const nextPath = opts.next || "/dashboard?tab=billing";
5713
+ const nextPath = opts.next || "/app/billing";
5714
5714
  try {
5715
5715
  const response = await authenticatedRequest(cliApiUrl("/cli/auth/web-handoff"), {
5716
5716
  method: "POST",
@@ -5725,7 +5725,7 @@ async function openAuthenticatedDashboard(opts = {}) {
5725
5725
  }
5726
5726
  } catch {
5727
5727
  }
5728
- const billingUrl = nextPath === "/dashboard?tab=billing" || nextPath === "/app/billing" ? DASHBOARD_BILLING_URL : assertSafeOpenUrl(`https://holdyourvoice.com${nextPath}`);
5728
+ const billingUrl = nextPath === "/app/billing" ? DASHBOARD_BILLING_URL : assertSafeOpenUrl(`https://holdyourvoice.com${nextPath}`);
5729
5729
  await (0, import_open.default)(billingUrl);
5730
5730
  }
5731
5731
  async function refreshToken(tokenOverride) {
@@ -5883,7 +5883,7 @@ async function request2(method, path27, body) {
5883
5883
  if (res.status === 401)
5884
5884
  throw new Error("your session expired. run: hyv init to sign in again.");
5885
5885
  if (res.status === 403)
5886
- throw new Error("you don't have access to this feature. check your plan at holdyourvoice.com/dashboard?tab=billing");
5886
+ throw new Error("you don't have access to this feature. check your plan at holdyourvoice.com/app/billing");
5887
5887
  if (!res.ok) {
5888
5888
  throw new Error(`something went wrong (${res.status}). try again or contact support.`);
5889
5889
  }
@@ -5943,7 +5943,9 @@ 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 subStatus = String(session.subscription_status || "").toLowerCase();
5947
+ const activeSubscription = !subStatus || ["active", "past_due", "trialing"].includes(subStatus);
5948
+ const hasPaidPlan = session.valid && activeSubscription && plan !== "none" && plan !== "free" && plan !== "expired" && plan !== "unknown" && plan !== "pending";
5947
5949
  const state = {
5948
5950
  authenticated: session.valid,
5949
5951
  hasPaidPlan,
@@ -5979,7 +5981,8 @@ async function requirePaidFeature(feature) {
5979
5981
  throw new Error("can't reach the server. check your internet connection and try again.");
5980
5982
  }
5981
5983
  const plan = (data.plan || "none").toLowerCase();
5982
- if (!data.plan || plan === "none" || data.status === "none") {
5984
+ const subStatus = String(data.subscription_status || data.status || "").toLowerCase();
5985
+ if (!data.plan || plan === "none" || plan === "free" || plan === "expired" || subStatus === "trialing" || subStatus === "none") {
5983
5986
  throw new Error(FEATURE_MESSAGES[feature]);
5984
5987
  }
5985
5988
  }
@@ -5994,7 +5997,7 @@ async function maybeShowLimitedModeHint(hasProfile) {
5994
5997
  } else if (!access.authenticated) {
5995
5998
  console.log(import_chalk5.default.dim("\n local mode \u2014 free scan engine. profiles + learning: hyv init"));
5996
5999
  } else {
5997
- console.log(import_chalk5.default.dim("\n local mode \u2014 upgrade for full profiles + learning: hyv plan --upgrade"));
6000
+ console.log(import_chalk5.default.dim("\n local mode \u2014 upgrade for full profiles + learning: hyv upgrade"));
5998
6001
  }
5999
6002
  }
6000
6003
  function formatModeLabel(access, hasFullProfile) {
@@ -6017,10 +6020,10 @@ var init_access = __esm({
6017
6020
  init_auth();
6018
6021
  init_api();
6019
6022
  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"
6023
+ profiles: "syncing voice profiles from your account requires a paid plan. run: hyv upgrade",
6024
+ learning: "the learning loop (reinforce, add) requires a paid plan. run: hyv upgrade",
6025
+ premiumPrompts: "rich profile-aware rewrite prompts require a paid plan. run: hyv upgrade",
6026
+ serverAnalysis: "server-assisted analysis requires a paid plan. run: hyv upgrade"
6024
6027
  };
6025
6028
  localOnlyOverride = false;
6026
6029
  cachedAccess = null;
@@ -11457,6 +11460,25 @@ var init_terminal_ui = __esm({
11457
11460
  });
11458
11461
 
11459
11462
  // src/lib/welcome-flow.ts
11463
+ function localProfilePath(name) {
11464
+ return path14.join(os8.homedir(), ".hyv", "profiles", `${name}.md`);
11465
+ }
11466
+ function listLocalProfileNames() {
11467
+ const profilesDir = path14.join(os8.homedir(), ".hyv", "profiles");
11468
+ if (!fs15.existsSync(profilesDir))
11469
+ return [];
11470
+ return fs15.readdirSync(profilesDir).filter((entry) => entry.endsWith(".md")).map((entry) => entry.slice(0, -3));
11471
+ }
11472
+ function formatPlanLabel(plan) {
11473
+ const labels = {
11474
+ individual: "Individual",
11475
+ multiple: "Multiple",
11476
+ solo: "Solo",
11477
+ team: "Team",
11478
+ agency: "Agency"
11479
+ };
11480
+ return labels[plan.toLowerCase()] || plan;
11481
+ }
11460
11482
  function readWelcomeState() {
11461
11483
  try {
11462
11484
  if (!fs15.existsSync(STATE_FILE)) {
@@ -11793,8 +11815,28 @@ function formatScanResult(text, profile) {
11793
11815
  }
11794
11816
  async function stepName() {
11795
11817
  console.log(import_chalk12.default.bold("\nstep 1 \xB7 name your profile\n"));
11818
+ const state = readWelcomeState();
11819
+ const existing = listLocalProfileNames();
11820
+ if (state.profile_name && existing.includes(state.profile_name)) {
11821
+ const reuse = await askYesNo(` reuse profile "${state.profile_name}"?`, true);
11822
+ if (reuse) {
11823
+ markStepComplete("name");
11824
+ return state.profile_name;
11825
+ }
11826
+ } else if (existing.length === 1) {
11827
+ const only = existing[0];
11828
+ const reuse = await askYesNo(` reuse existing profile "${only}"?`, true);
11829
+ if (reuse) {
11830
+ writeWelcomeState({ profile_name: only });
11831
+ markStepComplete("name");
11832
+ return only;
11833
+ }
11834
+ }
11796
11835
  const name = await askLine(import_chalk12.default.cyan(" profile name (e.g. my-voice): "));
11797
- return assertSafeProfileName(name);
11836
+ const safe = assertSafeProfileName(name);
11837
+ writeWelcomeState({ profile_name: safe });
11838
+ markStepComplete("name");
11839
+ return safe;
11798
11840
  }
11799
11841
  async function stepSamples(profileName) {
11800
11842
  console.log(import_chalk12.default.bold("\nstep 2 \xB7 add writing samples\n"));
@@ -11858,6 +11900,8 @@ _Add pasted samples to train this profile._
11858
11900
  console.log(import_chalk12.default.green(`
11859
11901
  \u2713 profile saved`));
11860
11902
  console.log(import_chalk12.default.dim(` ${saved}`));
11903
+ writeWelcomeState({ profile_name: profileName });
11904
+ markStepComplete("samples");
11861
11905
  }
11862
11906
  async function stepTest(profileName) {
11863
11907
  console.log(import_chalk12.default.bold("\nstep 3 \xB7 test on a draft"));
@@ -11898,42 +11942,25 @@ async function stepTest(profileName) {
11898
11942
  console.log(import_chalk12.default.dim(` try: hyv rewrite ${rewriteTarget} --profile ${profileName}`));
11899
11943
  markStepComplete("test");
11900
11944
  }
11901
- async function stepSignup(profileName) {
11902
- console.log(import_chalk12.default.bold("\nstep 4 \xB7 save & unlock\n"));
11903
- console.log(" your profile works on this machine. scan anything, anytime \u2014 free forever.");
11904
- console.log("");
11905
- console.log(" create a free account to back it up and sync everywhere.");
11906
- console.log(" then unlock learning for " + import_chalk12.default.bold("$1 your first month") + " \u2014 profiles that");
11907
- console.log(" get sharper every rewrite, hybrid rewrites, and your dashboard.\n");
11908
- console.log(import_chalk12.default.dim(" free forever (no account): scan, fix, check, mcp"));
11909
- console.log(import_chalk12.default.dim(" $1 first month: learning loop, rich rewrites, sync across devices\n"));
11910
- const ready = await askYesNo(" create your free account now? ($1 first month to unlock everything)");
11911
- if (!ready) {
11912
- console.log(import_chalk12.default.dim("\n no rush \u2014 your profile stays on this machine."));
11913
- console.log(import_chalk12.default.dim(" whenever you want backup + learning:"));
11914
- console.log(import_chalk12.default.dim(" hyv init"));
11915
- console.log(import_chalk12.default.dim(" hyv plan --upgrade ($1 first month)"));
11916
- console.log(import_chalk12.default.dim(` ${PRICING_URL}
11917
- `));
11918
- return;
11945
+ async function syncProfileToAccount(profileName) {
11946
+ const profilePath = localProfilePath(profileName);
11947
+ if (!fs15.existsSync(profilePath)) {
11948
+ console.log(import_chalk12.default.yellow(` no local profile at ${profilePath}`));
11949
+ return false;
11919
11950
  }
11920
11951
  if (!isInitialized() || !getToken()) {
11921
- console.log(import_chalk12.default.cyan("\n opening browser for signup (one sign-in)...\n"));
11922
- await withSpinner("creating your account\u2026", () => authenticateWithBrowser());
11952
+ console.log(import_chalk12.default.cyan("\n opening browser for sign-in...\n"));
11953
+ await withSpinner("signing in\u2026", () => authenticateWithBrowser());
11923
11954
  await briefPause();
11924
- console.log(import_chalk12.default.green(" \u2713 account created"));
11925
- } else {
11926
- console.log(import_chalk12.default.dim("\n already signed in \u2014 syncing profile..."));
11955
+ console.log(import_chalk12.default.green(" \u2713 signed in"));
11927
11956
  }
11928
- const content = fs15.readFileSync(
11929
- path14.join(os8.homedir(), ".hyv", "profiles", `${profileName}.md`),
11930
- "utf-8"
11931
- );
11957
+ const content = fs15.readFileSync(profilePath, "utf-8");
11932
11958
  try {
11933
11959
  const response = await withSpinner(
11934
11960
  "syncing profile\u2026",
11935
11961
  () => authenticatedRequest(cliApiUrl("/cli/profiles/new"), {
11936
11962
  method: "POST",
11963
+ timeout: PROFILE_SYNC_TIMEOUT_MS,
11937
11964
  body: { name: profileName, content, source: "welcome" }
11938
11965
  })
11939
11966
  );
@@ -11944,27 +11971,100 @@ async function stepSignup(profileName) {
11944
11971
  } else {
11945
11972
  console.log(import_chalk12.default.green(" \u2713 profile synced to your account"));
11946
11973
  }
11947
- } else {
11948
- const detail = response.data?.error;
11949
- console.log(import_chalk12.default.yellow(
11950
- ` profile saved locally \u2014 retry \`hyv welcome\` when online${detail ? ` (${detail})` : ` (HTTP ${response.status})`}`
11951
- ));
11974
+ return true;
11952
11975
  }
11976
+ const detail = response.data?.error;
11977
+ console.log(import_chalk12.default.yellow(
11978
+ ` profile saved locally \u2014 retry \`hyv sync\`${detail ? ` (${detail})` : ` (HTTP ${response.status})`}`
11979
+ ));
11953
11980
  } catch (err) {
11954
11981
  console.log(import_chalk12.default.yellow(
11955
- ` profile saved locally \u2014 retry \`hyv welcome\` (${err?.message || "sync failed"})`
11982
+ ` profile saved locally \u2014 retry \`hyv sync\` (${err?.message || "sync failed"})`
11956
11983
  ));
11957
11984
  }
11985
+ return false;
11986
+ }
11987
+ async function stepSignup(profileName) {
11988
+ console.log(import_chalk12.default.bold("\nstep 4 \xB7 save & unlock\n"));
11989
+ const access = await getAccessState();
11990
+ if (access.hasPaidPlan) {
11991
+ console.log(` you're on ${import_chalk12.default.bold(formatPlanLabel(access.plan))} \u2014 learning, sync, and dashboard are unlocked.`);
11992
+ console.log(import_chalk12.default.dim("\n syncing your local profile to your account..."));
11993
+ await syncProfileToAccount(profileName);
11994
+ markStepComplete("signup");
11995
+ console.log(import_chalk12.default.dim("\n run `hyv scan draft.md` or `hyv sync` anytime.\n"));
11996
+ return;
11997
+ }
11998
+ console.log(" your profile works on this machine. scan anything, anytime \u2014 free forever.");
11999
+ console.log("");
12000
+ if (access.authenticated) {
12001
+ console.log(" you're signed in. sync this profile, or upgrade for learning + rich rewrites.");
12002
+ console.log(import_chalk12.default.dim("\n free forever: scan, fix, check, mcp"));
12003
+ console.log(import_chalk12.default.dim(" paid: learning loop, hybrid rewrites, sync across devices\n"));
12004
+ const syncNow = await askYesNo(" sync profile to your account now?", true);
12005
+ if (syncNow) {
12006
+ await syncProfileToAccount(profileName);
12007
+ }
12008
+ const upgrade = await askYesNo(" open billing to upgrade?", false);
12009
+ if (upgrade) {
12010
+ await withSpinner("opening billing\u2026", () => openAuthenticatedDashboard({ next: "/app/billing" }));
12011
+ await briefPause();
12012
+ }
12013
+ markStepComplete("signup");
12014
+ console.log(import_chalk12.default.dim("\n upgrade anytime: `hyv plan --upgrade`\n"));
12015
+ return;
12016
+ }
12017
+ console.log(" create a free account to back it up and sync everywhere.");
12018
+ console.log(" then unlock learning for " + import_chalk12.default.bold("$1 your first month") + " \u2014 profiles that");
12019
+ console.log(" get sharper every rewrite, hybrid rewrites, and your dashboard.\n");
12020
+ console.log(import_chalk12.default.dim(" free forever (no account): scan, fix, check, mcp"));
12021
+ console.log(import_chalk12.default.dim(" $1 first month: learning loop, rich rewrites, sync across devices\n"));
12022
+ const ready = await askYesNo(" create your free account now? ($1 first month to unlock everything)");
12023
+ if (!ready) {
12024
+ console.log(import_chalk12.default.dim("\n no rush \u2014 your profile stays on this machine."));
12025
+ console.log(import_chalk12.default.dim(" whenever you want backup + learning:"));
12026
+ console.log(import_chalk12.default.dim(" hyv init"));
12027
+ console.log(import_chalk12.default.dim(" hyv plan --upgrade ($1 first month)"));
12028
+ console.log(import_chalk12.default.dim(` ${PRICING_URL}
12029
+ `));
12030
+ return;
12031
+ }
12032
+ await syncProfileToAccount(profileName);
11958
12033
  console.log(import_chalk12.default.cyan("\n opening billing in your dashboard ($1 first month)..."));
11959
- await withSpinner("opening billing\u2026", () => openAuthenticatedDashboard({ next: "/dashboard?tab=billing" }));
12034
+ await withSpinner("opening billing\u2026", () => openAuthenticatedDashboard({ next: "/app/billing" }));
11960
12035
  await briefPause();
11961
12036
  markStepComplete("signup");
11962
12037
  console.log(import_chalk12.default.dim("\n you're signed in \u2014 pick a plan in billing, no second login.\n"));
11963
12038
  }
12039
+ async function maybeRunPaidWelcomeShortcut() {
12040
+ const access = await getAccessState();
12041
+ if (!access.authenticated || !access.hasPaidPlan)
12042
+ return null;
12043
+ const state = readWelcomeState();
12044
+ const profiles = listLocalProfileNames();
12045
+ const profileName = state.profile_name && profiles.includes(state.profile_name) ? state.profile_name : profiles[0];
12046
+ if (!profileName)
12047
+ return null;
12048
+ console.log(import_chalk12.default.green(`
12049
+ ${formatPlanLabel(access.plan)} plan active \u2014 profile "${profileName}" ready.`));
12050
+ const resync = await askYesNo(" sync profile to your account now?", true);
12051
+ if (resync) {
12052
+ await syncProfileToAccount(profileName);
12053
+ }
12054
+ markStepComplete("signup");
12055
+ console.log(import_chalk12.default.green("\ndone \u2014 your voice profile is ready.\n"));
12056
+ console.log(import_chalk12.default.dim(" hyv scan draft.md"));
12057
+ console.log(import_chalk12.default.dim(` hyv rewrite draft.md --profile ${profileName}`));
12058
+ console.log(import_chalk12.default.dim(" hyv mcp --setup\n"));
12059
+ return profileName;
12060
+ }
11964
12061
  async function runInteractiveWelcome() {
11965
12062
  recordEvent("welcome_interactive");
11966
12063
  console.log("\n" + buildWelcomeHeader());
11967
12064
  try {
12065
+ const shortcut = await maybeRunPaidWelcomeShortcut();
12066
+ if (shortcut)
12067
+ return;
11968
12068
  const profileName = await stepName();
11969
12069
  await stepSamples(profileName);
11970
12070
  await stepTest(profileName);
@@ -11991,7 +12091,7 @@ function getMcpWelcomeResponse(args2) {
11991
12091
  }
11992
12092
  return buildWelcomeGuide({ profileName: args2.profile, forLlm: true });
11993
12093
  }
11994
- var import_chalk12, fs15, http2, https2, os8, path14, readline, WELCOME_TAGLINE, FLOW_STEPS, STATE_FILE;
12094
+ var import_chalk12, fs15, http2, https2, os8, path14, readline, PROFILE_SYNC_TIMEOUT_MS, WELCOME_TAGLINE, FLOW_STEPS, STATE_FILE;
11995
12095
  var init_welcome_flow = __esm({
11996
12096
  "src/lib/welcome-flow.ts"() {
11997
12097
  "use strict";
@@ -12008,10 +12108,12 @@ var init_welcome_flow = __esm({
12008
12108
  init_terminal_ui();
12009
12109
  init_config();
12010
12110
  init_auth();
12111
+ init_access();
12011
12112
  init_scan();
12012
12113
  init_free_paid();
12013
12114
  init_telemetry();
12014
12115
  init_document_text();
12116
+ PROFILE_SYNC_TIMEOUT_MS = 9e4;
12015
12117
  WELCOME_TAGLINE = "Hold Your Voice \u2014 make your AI agents sound exactly like you.";
12016
12118
  FLOW_STEPS = [
12017
12119
  { n: 1, key: "name", title: "name your profile", hint: "pick a short name \u2014 e.g. my-voice" },
@@ -12136,6 +12238,54 @@ In conclusion, the key to success is to empower your team with actionable insigh
12136
12238
  }
12137
12239
  });
12138
12240
 
12241
+ // src/lib/billing-upgrade.ts
12242
+ var billing_upgrade_exports = {};
12243
+ __export(billing_upgrade_exports, {
12244
+ openBillingUpgrade: () => openBillingUpgrade
12245
+ });
12246
+ async function openBillingUpgrade(opts = {}) {
12247
+ const plan = opts.plan || "individual";
12248
+ const next = `/app/billing?checkout=${plan}`;
12249
+ const token = getToken();
12250
+ if (!token) {
12251
+ console.log(import_chalk14.default.cyan("\nSign in to upgrade \u2014 opening browser...\n"));
12252
+ try {
12253
+ await authenticateWithBrowser();
12254
+ } catch {
12255
+ console.log(import_chalk14.default.yellow("Sign-in cancelled or failed."));
12256
+ console.log(import_chalk14.default.dim(`Visit ${DASHBOARD_BILLING_URL} after running hyv init`));
12257
+ return;
12258
+ }
12259
+ }
12260
+ const access = await getAccessState();
12261
+ if (access.hasPaidPlan) {
12262
+ console.log(import_chalk14.default.green(`
12263
+ \u2713 You already have a paid plan (${access.plan}).`));
12264
+ console.log(import_chalk14.default.dim("Manage billing: hyv plan --manage\n"));
12265
+ return;
12266
+ }
12267
+ console.log(import_chalk14.default.cyan("\nOpening billing in your dashboard ($1 first month)...\n"));
12268
+ try {
12269
+ await openAuthenticatedDashboard({ next });
12270
+ console.log(import_chalk14.default.green("\n\u2713 Dashboard opened \u2014 pick a plan in billing"));
12271
+ console.log(import_chalk14.default.dim("Checkout opens automatically when you arrive from the CLI."));
12272
+ } catch {
12273
+ console.log(import_chalk14.default.yellow("Could not open dashboard automatically."));
12274
+ console.log(import_chalk14.default.dim(`Visit https://holdyourvoice.com${next} after hyv init`));
12275
+ }
12276
+ }
12277
+ var import_chalk14;
12278
+ var init_billing_upgrade = __esm({
12279
+ "src/lib/billing-upgrade.ts"() {
12280
+ "use strict";
12281
+ import_chalk14 = __toESM(require_source());
12282
+ init_access();
12283
+ init_config();
12284
+ init_auth();
12285
+ init_free_paid();
12286
+ }
12287
+ });
12288
+
12139
12289
  // node_modules/glob/dist/commonjs/index.min.js
12140
12290
  var require_index_min = __commonJS({
12141
12291
  "node_modules/glob/dist/commonjs/index.min.js"(exports2) {
@@ -15817,7 +15967,7 @@ function registerStatusCommand(program3) {
15817
15967
  if (latest && current !== "unknown" && compareSemver(current, latest) < 0) {
15818
15968
  console.log(import_chalk7.default.bold("\nUpdate"));
15819
15969
  console.log(import_chalk7.default.cyan(` ${current} \u2192 ${latest} available`));
15820
- console.log(import_chalk7.default.dim(" Run: hyv upgrade"));
15970
+ console.log(import_chalk7.default.dim(" Run: npm i -g @holdyourvoice/hyv@latest"));
15821
15971
  }
15822
15972
  console.log("");
15823
15973
  });
@@ -16913,7 +17063,7 @@ function generateLocalProfileFromStats(name, stats) {
16913
17063
  }
16914
17064
 
16915
17065
  // src/commands/plan.ts
16916
- var import_chalk14 = __toESM(require_source());
17066
+ var import_chalk15 = __toESM(require_source());
16917
17067
  init_config();
16918
17068
  init_auth();
16919
17069
  var import_open2 = __toESM(require_open());
@@ -16928,10 +17078,10 @@ function registerPlanCommand(program3) {
16928
17078
  }
16929
17079
  const token = getToken();
16930
17080
  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"));
17081
+ console.log(import_chalk15.default.yellow("\nNot authenticated \u2014 free tier still works.\n"));
17082
+ console.log(import_chalk15.default.dim(" hyv scan draft.md | hyv welcome | npx @holdyourvoice/hyv scan draft.md"));
16933
17083
  printFreePaidMatrix({ compact: true });
16934
- console.log(import_chalk14.default.dim(" Run `hyv init` for profiles + learning.\n"));
17084
+ console.log(import_chalk15.default.dim(" Run `hyv init` for profiles + learning.\n"));
16935
17085
  return;
16936
17086
  }
16937
17087
  if (options.upgrade) {
@@ -16944,20 +17094,20 @@ function registerPlanCommand(program3) {
16944
17094
  await showPlan();
16945
17095
  }
16946
17096
  } catch (error) {
16947
- console.error(import_chalk14.default.red(`
17097
+ console.error(import_chalk15.default.red(`
16948
17098
  Error: ${error.message}`));
16949
17099
  process.exit(1);
16950
17100
  }
16951
17101
  });
16952
17102
  }
16953
17103
  async function showPlan() {
16954
- console.log(import_chalk14.default.bold("\nSubscription Plan\n"));
17104
+ console.log(import_chalk15.default.bold("\nSubscription Plan\n"));
16955
17105
  const response = await authenticatedRequest(
16956
17106
  cliApiUrl("/cli/heartbeat"),
16957
17107
  { method: "GET" }
16958
17108
  );
16959
17109
  if (response.status !== 200) {
16960
- console.log(import_chalk14.default.yellow("Could not fetch plan info."));
17110
+ console.log(import_chalk15.default.yellow("Could not fetch plan info."));
16961
17111
  return;
16962
17112
  }
16963
17113
  const data = response.data;
@@ -16975,39 +17125,31 @@ async function showPlan() {
16975
17125
  team: "$29/mo",
16976
17126
  agency: "Custom"
16977
17127
  };
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");
17128
+ console.log(import_chalk15.default.dim("Plan:"), import_chalk15.default.bold(planNames[plan] || plan));
17129
+ console.log(import_chalk15.default.dim("Price:"), planPrices[plan] || "-");
17130
+ console.log(import_chalk15.default.dim("Status:"), data.subscription_status || "none");
16981
17131
  if (license) {
16982
- console.log(import_chalk14.default.dim("License:"), license.key_hint);
17132
+ console.log(import_chalk15.default.dim("License:"), license.key_hint);
16983
17133
  }
16984
17134
  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"));
17135
+ console.log(import_chalk15.default.bold("\nFree tier (always)"));
17136
+ console.log(import_chalk15.default.dim(" local scan, fix, check, mcp, all web tools \u2014 hyv welcome"));
16987
17137
  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"));
17138
+ console.log(import_chalk15.default.bold("\nUpgrade unlocks"));
17139
+ console.log(import_chalk15.default.dim(" profiles, learning loop, hybrid analysis, rich rewrites"));
17140
+ console.log(import_chalk15.default.dim(` ${PRICING_URL}`));
17141
+ console.log(import_chalk15.default.dim("\n hyv plan --upgrade | hyv plan --free for full matrix"));
16992
17142
  } else {
16993
17143
  console.log("\nManage your subscription:");
16994
- console.log(import_chalk14.default.dim(" hyv plan --manage"));
17144
+ console.log(import_chalk15.default.dim(" hyv plan --manage"));
16995
17145
  }
16996
17146
  }
16997
17147
  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
- }
17148
+ const { openBillingUpgrade: openBillingUpgrade2 } = await Promise.resolve().then(() => (init_billing_upgrade(), billing_upgrade_exports));
17149
+ await openBillingUpgrade2({ plan: "individual" });
17008
17150
  }
17009
17151
  async function openBillingPortal() {
17010
- console.log(import_chalk14.default.cyan("\nOpening billing portal...\n"));
17152
+ console.log(import_chalk15.default.cyan("\nOpening billing portal...\n"));
17011
17153
  const response = await authenticatedRequest(
17012
17154
  cliApiUrl("/cli/subscribe/manage"),
17013
17155
  { method: "POST" }
@@ -17016,41 +17158,41 @@ async function openBillingPortal() {
17016
17158
  const data = response.data;
17017
17159
  const portalUrl = data.portal_url;
17018
17160
  if (portalUrl) {
17019
- console.log(import_chalk14.default.dim("Opening browser..."));
17161
+ console.log(import_chalk15.default.dim("Opening browser..."));
17020
17162
  await (0, import_open2.default)(assertSafeOpenUrl(portalUrl));
17021
- console.log(import_chalk14.default.green("\n\u2713 Billing portal opened"));
17163
+ console.log(import_chalk15.default.green("\n\u2713 Billing portal opened"));
17022
17164
  } else {
17023
- console.log(import_chalk14.default.yellow("No portal URL received."));
17165
+ console.log(import_chalk15.default.yellow("No portal URL received."));
17024
17166
  }
17025
17167
  } 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.`));
17168
+ console.log(import_chalk15.default.yellow("Could not open billing portal."));
17169
+ console.log(import_chalk15.default.dim(`Visit ${DASHBOARD_BILLING_URL} to manage billing.`));
17028
17170
  }
17029
17171
  }
17030
17172
  async function downgradePlan() {
17031
- console.log(import_chalk14.default.yellow("\nDowngrade Plan\n"));
17173
+ console.log(import_chalk15.default.yellow("\nDowngrade Plan\n"));
17032
17174
  console.log("To downgrade your plan, please visit:");
17033
- console.log(import_chalk14.default.dim(` ${DASHBOARD_BILLING_URL}`));
17175
+ console.log(import_chalk15.default.dim(` ${DASHBOARD_BILLING_URL}`));
17034
17176
  console.log("\nOr contact support at shashank@holdyourvoice.com");
17035
17177
  }
17036
17178
 
17037
17179
  // src/commands/scan.ts
17038
- var import_chalk17 = __toESM(require_source());
17180
+ var import_chalk18 = __toESM(require_source());
17039
17181
  init_pipeline();
17040
17182
  init_local_profile();
17041
17183
  init_access();
17042
17184
 
17043
17185
  // src/lib/output.ts
17044
- var import_chalk15 = __toESM(require_source());
17186
+ var import_chalk16 = __toESM(require_source());
17045
17187
  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)
17188
+ dim: (s) => import_chalk16.default.dim(s),
17189
+ bold: (s) => import_chalk16.default.bold(s),
17190
+ accent: (s) => import_chalk16.default.hex("#C4441A")(s),
17191
+ green: (s) => import_chalk16.default.green(s),
17192
+ red: (s) => import_chalk16.default.red(s),
17193
+ yellow: (s) => import_chalk16.default.yellow(s),
17194
+ cyan: (s) => import_chalk16.default.cyan(s),
17195
+ white: (s) => import_chalk16.default.white(s)
17054
17196
  };
17055
17197
  function logo() {
17056
17198
  return `${c.bold("hold your ")}${c.accent("voice")}`;
@@ -17198,7 +17340,7 @@ async function runHybridAnalysis(text, profile, opts = {}) {
17198
17340
  }
17199
17341
 
17200
17342
  // src/commands/history.ts
17201
- var import_chalk16 = __toESM(require_source());
17343
+ var import_chalk17 = __toESM(require_source());
17202
17344
  var fs17 = __toESM(require("fs"));
17203
17345
  var path16 = __toESM(require("path"));
17204
17346
  init_config();
@@ -17250,7 +17392,7 @@ function registerHistoryCommand(program3) {
17250
17392
  if (fs17.existsSync(HISTORY_FILE)) {
17251
17393
  fs17.unlinkSync(HISTORY_FILE);
17252
17394
  }
17253
- console.log(import_chalk16.default.green("\n\u2713 History cleared"));
17395
+ console.log(import_chalk17.default.green("\n\u2713 History cleared"));
17254
17396
  return;
17255
17397
  }
17256
17398
  let entries = readHistory();
@@ -17264,14 +17406,14 @@ function registerHistoryCommand(program3) {
17264
17406
  const limit = parseInt(options.limit, 10);
17265
17407
  entries = entries.slice(-limit);
17266
17408
  if (entries.length === 0) {
17267
- console.log(import_chalk16.default.dim("\nNo scan history yet. Run hyv scan or hyv score to start tracking."));
17409
+ console.log(import_chalk17.default.dim("\nNo scan history yet. Run hyv scan or hyv score to start tracking."));
17268
17410
  return;
17269
17411
  }
17270
17412
  if (options.format === "json") {
17271
17413
  console.log(JSON.stringify(entries, null, 2));
17272
17414
  return;
17273
17415
  }
17274
- console.log(import_chalk16.default.bold(`
17416
+ console.log(import_chalk17.default.bold(`
17275
17417
  score history (last ${entries.length} scans)
17276
17418
  `));
17277
17419
  if (options.chart) {
@@ -17283,7 +17425,7 @@ function registerHistoryCommand(program3) {
17283
17425
  if (min !== max) {
17284
17426
  console.log(` ${min} \u2524`);
17285
17427
  }
17286
- console.log(import_chalk16.default.dim(` \u2514${"\u2500".repeat(sl.length + 1)}`));
17428
+ console.log(import_chalk17.default.dim(` \u2514${"\u2500".repeat(sl.length + 1)}`));
17287
17429
  console.log("");
17288
17430
  }
17289
17431
  const scores = entries.map((e) => e.score);
@@ -17296,22 +17438,22 @@ function registerHistoryCommand(program3) {
17296
17438
  const firstAvg = firstHalf.reduce((s, e) => s + e.score, 0) / (firstHalf.length || 1);
17297
17439
  const secondAvg = secondHalf.reduce((s, e) => s + e.score, 0) / (secondHalf.length || 1);
17298
17440
  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"));
17441
+ 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");
17442
+ console.log(import_chalk17.default.dim(` avg: ${avg} best: ${best.score} worst: ${worst.score}`));
17443
+ console.log(import_chalk17.default.dim(` trend: ${trendStr}`));
17444
+ console.log(import_chalk17.default.bold("\n recent:\n"));
17303
17445
  const recent = entries.slice(-10).reverse();
17304
17446
  for (const entry of recent) {
17305
17447
  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");
17448
+ const icon = entry.issues === 0 ? import_chalk17.default.green("\u2713") : import_chalk17.default.red("\u25CF");
17449
+ 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`);
17450
+ const issues = entry.issues > 0 ? import_chalk17.default.red(`${entry.issues} issues`) : import_chalk17.default.dim("clean");
17309
17451
  const file = path16.basename(entry.file).slice(0, 25).padEnd(25);
17310
- console.log(` ${import_chalk16.default.dim(time)} ${icon} ${file} ${score} ${issues}`);
17452
+ console.log(` ${import_chalk17.default.dim(time)} ${icon} ${file} ${score} ${issues}`);
17311
17453
  }
17312
17454
  console.log("");
17313
17455
  } catch (error) {
17314
- console.error(import_chalk16.default.red(`Error: ${error.message}`));
17456
+ console.error(import_chalk17.default.red(`Error: ${error.message}`));
17315
17457
  process.exit(1);
17316
17458
  }
17317
17459
  });
@@ -17326,7 +17468,7 @@ function registerScanCommand(program3) {
17326
17468
  const profile = await loadProfileForCommand(options.profile);
17327
17469
  const { text, path: filePath } = readText(file);
17328
17470
  if (!text.trim()) {
17329
- console.warn(import_chalk17.default.yellow("File is empty or contains only whitespace."));
17471
+ console.warn(import_chalk18.default.yellow("File is empty or contains only whitespace."));
17330
17472
  process.exit(0);
17331
17473
  }
17332
17474
  const ignoreRules = options.ignore ? new Set(options.ignore.split(",").map((r) => r.trim())) : /* @__PURE__ */ new Set();
@@ -17369,26 +17511,26 @@ function registerScanCommand(program3) {
17369
17511
  }, null, 2));
17370
17512
  } else {
17371
17513
  if (signals.length === 0) {
17372
- console.log(import_chalk17.default.green(`
17514
+ console.log(import_chalk18.default.green(`
17373
17515
  \u2713 No issues found in ${filePath}`));
17374
- console.log(import_chalk17.default.dim(` score: ${score}/100`));
17516
+ console.log(import_chalk18.default.dim(` score: ${score}/100`));
17375
17517
  } else {
17376
- console.log(import_chalk17.default.bold(`
17518
+ console.log(import_chalk18.default.bold(`
17377
17519
  hyv scan ${filePath}`));
17378
17520
  if (profile) {
17379
- console.log(import_chalk17.default.dim(` profile: ${profile.slug || profile.name}${hasRichProfile(profile) ? " (full)" : ""}`));
17521
+ console.log(import_chalk18.default.dim(` profile: ${profile.slug || profile.name}${hasRichProfile(profile) ? " (full)" : ""}`));
17380
17522
  }
17381
17523
  if (analysis.message) {
17382
- console.log(import_chalk17.default.dim(` engine: ${analysis.message}`));
17524
+ console.log(import_chalk18.default.dim(` engine: ${analysis.message}`));
17383
17525
  }
17384
17526
  console.log("");
17385
17527
  printGroupedSignals(signals, profile);
17386
- console.log(import_chalk17.default.yellow(`
17528
+ console.log(import_chalk18.default.yellow(`
17387
17529
  ${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(`
17530
+ console.log(import_chalk18.default.dim(` score: ${score}/100`));
17531
+ console.log(import_chalk18.default.dim(`
17390
17532
  fix: hyv fix ${file}`));
17391
- console.log(import_chalk17.default.dim(` diff: hyv diff ${file}
17533
+ console.log(import_chalk18.default.dim(` diff: hyv diff ${file}
17392
17534
  `));
17393
17535
  }
17394
17536
  await maybeShowLimitedModeHint(!!profile);
@@ -17406,14 +17548,14 @@ hyv scan ${filePath}`));
17406
17548
  process.exit(2);
17407
17549
  }
17408
17550
  } catch (error) {
17409
- console.error(import_chalk17.default.red(`Error: ${error.message}`));
17551
+ console.error(import_chalk18.default.red(`Error: ${error.message}`));
17410
17552
  process.exit(1);
17411
17553
  }
17412
17554
  });
17413
17555
  }
17414
17556
 
17415
17557
  // src/commands/doctor.ts
17416
- var import_chalk18 = __toESM(require_source());
17558
+ var import_chalk19 = __toESM(require_source());
17417
17559
  var fs19 = __toESM(require("fs"));
17418
17560
  var path18 = __toESM(require("path"));
17419
17561
  var os9 = __toESM(require("os"));
@@ -17579,112 +17721,112 @@ function readMcpHyv(configFile) {
17579
17721
  }
17580
17722
  function registerDoctorCommand(program3) {
17581
17723
  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"));
17724
+ console.log(import_chalk19.default.bold("\nhold your voice \u2014 doctor\n"));
17583
17725
  let issues = 0;
17584
17726
  let fixed = 0;
17585
- console.log(import_chalk18.default.dim(`engine: ${getEngineLabel()} (node ${process.version})`));
17727
+ console.log(import_chalk19.default.dim(`engine: ${getEngineLabel()} (node ${process.version})`));
17586
17728
  if (isLocalOnlyMode()) {
17587
- console.log(import_chalk18.default.yellow(" local-only mode: HYV_LOCAL_ONLY is set"));
17729
+ console.log(import_chalk19.default.yellow(" local-only mode: HYV_LOCAL_ONLY is set"));
17588
17730
  }
17589
17731
  const access = await getAccessState();
17590
17732
  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..."));
17733
+ console.log(import_chalk19.default.dim(`mode: ${formatModeLabel(access, hasRichProfile(profile))}`));
17734
+ console.log(import_chalk19.default.dim("tip: run hyv welcome for free capabilities\n"));
17735
+ console.log(import_chalk19.default.dim("checking cli installation..."));
17594
17736
  const cliPath = process.argv[1];
17595
17737
  if (cliPath && fs19.existsSync(cliPath)) {
17596
- console.log(import_chalk18.default.green(" \u2713 cli installed"));
17738
+ console.log(import_chalk19.default.green(" \u2713 cli installed"));
17597
17739
  } else {
17598
- console.log(import_chalk18.default.red(" \u2717 cli not found"));
17740
+ console.log(import_chalk19.default.red(" \u2717 cli not found"));
17599
17741
  issues++;
17600
17742
  }
17601
- console.log(import_chalk18.default.dim("checking .hyv directory..."));
17743
+ console.log(import_chalk19.default.dim("checking .hyv directory..."));
17602
17744
  if (fs19.existsSync(HYV_DIR)) {
17603
- console.log(import_chalk18.default.green(" \u2713 .hyv directory exists"));
17745
+ console.log(import_chalk19.default.green(" \u2713 .hyv directory exists"));
17604
17746
  } else {
17605
- console.log(import_chalk18.default.yellow(" ! .hyv directory missing \u2014 creating..."));
17747
+ console.log(import_chalk19.default.yellow(" ! .hyv directory missing \u2014 creating..."));
17606
17748
  fs19.mkdirSync(HYV_DIR, { recursive: true, mode: 448 });
17607
17749
  fixed++;
17608
17750
  }
17609
- console.log(import_chalk18.default.dim("checking cache..."));
17751
+ console.log(import_chalk19.default.dim("checking cache..."));
17610
17752
  const diskProfiles = listDiskCachedProfiles();
17611
17753
  const syncMeta = path18.join(CACHE_DIR2, "sync-meta.json");
17612
17754
  if (diskProfiles.length > 0 || fs19.existsSync(syncMeta)) {
17613
- console.log(import_chalk18.default.green(` \u2713 profile cache (${diskProfiles.length} full profile(s))`));
17755
+ console.log(import_chalk19.default.green(` \u2713 profile cache (${diskProfiles.length} full profile(s))`));
17614
17756
  if (fs19.existsSync(syncMeta)) {
17615
17757
  try {
17616
17758
  const meta = JSON.parse(fs19.readFileSync(syncMeta, "utf-8"));
17617
- console.log(import_chalk18.default.dim(` last sync: ${meta.synced_at || "unknown"}`));
17759
+ console.log(import_chalk19.default.dim(` last sync: ${meta.synced_at || "unknown"}`));
17618
17760
  } catch {
17619
17761
  }
17620
17762
  }
17621
17763
  } else {
17622
- console.log(import_chalk18.default.dim(" - no full profile cache (free local engine still works)"));
17764
+ console.log(import_chalk19.default.dim(" - no full profile cache (free local engine still works)"));
17623
17765
  }
17624
- console.log(import_chalk18.default.dim("checking file permissions..."));
17766
+ console.log(import_chalk19.default.dim("checking file permissions..."));
17625
17767
  if (fs19.existsSync(HYV_DIR)) {
17626
17768
  const hyvMode = fs19.statSync(HYV_DIR).mode & 511;
17627
17769
  if ((hyvMode & 63) === 0) {
17628
- console.log(import_chalk18.default.green(" \u2713 .hyv directory permissions"));
17770
+ console.log(import_chalk19.default.green(" \u2713 .hyv directory permissions"));
17629
17771
  } 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"));
17772
+ console.log(import_chalk19.default.yellow(" ! .hyv directory is world/group accessible"));
17773
+ console.log(import_chalk19.default.dim(" run: chmod 700 ~/.hyv"));
17632
17774
  issues++;
17633
17775
  }
17634
17776
  }
17635
17777
  if (fs19.existsSync(AUTH_FILE)) {
17636
17778
  if (isOwnerOnlyFile(AUTH_FILE)) {
17637
- console.log(import_chalk18.default.green(" \u2713 auth.json permissions"));
17779
+ console.log(import_chalk19.default.green(" \u2713 auth.json permissions"));
17638
17780
  } 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"));
17781
+ console.log(import_chalk19.default.yellow(" ! auth.json is world/group readable"));
17782
+ console.log(import_chalk19.default.dim(" run: chmod 600 ~/.hyv/auth.json"));
17641
17783
  issues++;
17642
17784
  }
17643
17785
  }
17644
- console.log(import_chalk18.default.dim("checking authentication..."));
17786
+ console.log(import_chalk19.default.dim("checking authentication..."));
17645
17787
  if (isInitialized()) {
17646
17788
  const auth = readAuth();
17647
17789
  if (auth) {
17648
- console.log(import_chalk18.default.green(" \u2713 authenticated"));
17649
- console.log(import_chalk18.default.dim(` email: ${auth.user?.email || "unknown"}`));
17790
+ console.log(import_chalk19.default.green(" \u2713 authenticated"));
17791
+ console.log(import_chalk19.default.dim(` email: ${auth.user?.email || "unknown"}`));
17650
17792
  const session = await checkSession();
17651
17793
  if (session.valid) {
17652
- console.log(import_chalk18.default.green(" \u2713 session valid"));
17653
- console.log(import_chalk18.default.dim(` plan: ${session.plan || "none"}`));
17794
+ console.log(import_chalk19.default.green(" \u2713 session valid"));
17795
+ console.log(import_chalk19.default.dim(` plan: ${session.plan || "none"}`));
17654
17796
  } else {
17655
- console.log(import_chalk18.default.red(" \u2717 session expired"));
17656
- console.log(import_chalk18.default.dim(" run: hyv init"));
17797
+ console.log(import_chalk19.default.red(" \u2717 session expired"));
17798
+ console.log(import_chalk19.default.dim(" run: hyv init"));
17657
17799
  issues++;
17658
17800
  }
17659
17801
  } else {
17660
- console.log(import_chalk18.default.red(" \u2717 auth data missing"));
17802
+ console.log(import_chalk19.default.red(" \u2717 auth data missing"));
17661
17803
  issues++;
17662
17804
  }
17663
17805
  } 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"));
17806
+ console.log(import_chalk19.default.yellow(" ! not authenticated (free local scan works)"));
17807
+ console.log(import_chalk19.default.dim(" run: hyv init for profiles + learning"));
17666
17808
  }
17667
- console.log(import_chalk18.default.dim("checking voice profile..."));
17809
+ console.log(import_chalk19.default.dim("checking voice profile..."));
17668
17810
  const voiceMd = path18.join(HYV_DIR, "voice.md");
17669
17811
  const hasVoiceMd = fs19.existsSync(voiceMd) && fs19.readFileSync(voiceMd, "utf-8").trim().length > 50;
17670
17812
  const profileFiles = fs19.existsSync(PROFILES_DIR) ? fs19.readdirSync(PROFILES_DIR).filter((f) => f.endsWith(".md") && f !== "voice.md") : [];
17671
17813
  if (hasVoiceMd || profileFiles.length > 0 || diskProfiles.length > 0) {
17672
17814
  if (hasVoiceMd)
17673
- console.log(import_chalk18.default.green(" \u2713 voice.md exists"));
17815
+ console.log(import_chalk19.default.green(" \u2713 voice.md exists"));
17674
17816
  if (profileFiles.length > 0)
17675
- console.log(import_chalk18.default.green(` \u2713 ${profileFiles.length} markdown profile(s)`));
17817
+ console.log(import_chalk19.default.green(` \u2713 ${profileFiles.length} markdown profile(s)`));
17676
17818
  if (diskProfiles.length > 0)
17677
- console.log(import_chalk18.default.green(` \u2713 ${diskProfiles.length} full cached profile(s)`));
17819
+ console.log(import_chalk19.default.green(` \u2713 ${diskProfiles.length} full cached profile(s)`));
17678
17820
  } 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"));
17821
+ console.log(import_chalk19.default.yellow(" ! no voice profile (optional for free scan)"));
17822
+ console.log(import_chalk19.default.dim(" run: hyv new <name> or hyv init"));
17681
17823
  }
17682
- console.log(import_chalk18.default.dim("checking agent configurations..."));
17824
+ console.log(import_chalk19.default.dim("checking agent configurations..."));
17683
17825
  const cursorLegacyRule = path18.join(HOME, ".cursor", "rules", "hyv.md");
17684
17826
  const cursorRule = path18.join(HOME, ".cursor", "rules", "hyv.mdc");
17685
17827
  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)"));
17828
+ console.log(import_chalk19.default.yellow(" ! stale cursor rule ~/.cursor/rules/hyv.md (use hyv.mdc)"));
17829
+ console.log(import_chalk19.default.dim(" run: rm ~/.cursor/rules/hyv.md (or hyv doctor --fix-agents)"));
17688
17830
  issues++;
17689
17831
  }
17690
17832
  const agMcpFile = path18.join(HOME, ".gemini", "config", "mcp_config.json");
@@ -17704,9 +17846,9 @@ function registerDoctorCommand(program3) {
17704
17846
  ];
17705
17847
  for (const agent of agentChecks) {
17706
17848
  if (agent.ok) {
17707
- console.log(import_chalk18.default.green(` \u2713 ${agent.name}`));
17849
+ console.log(import_chalk19.default.green(` \u2713 ${agent.name}`));
17708
17850
  } else {
17709
- console.log(import_chalk18.default.dim(` - ${agent.name} not configured`));
17851
+ console.log(import_chalk19.default.dim(` - ${agent.name} not configured`));
17710
17852
  }
17711
17853
  }
17712
17854
  if (opts.fixAgents) {
@@ -17714,84 +17856,84 @@ function registerDoctorCommand(program3) {
17714
17856
  const pkgDir = path18.resolve(__dirname, "..");
17715
17857
  const { setupAgents } = require(path18.join(pkgDir, "scripts", "postinstall-lib.js"));
17716
17858
  const result = setupAgents({ pkgDir, quiet: true });
17717
- console.log(import_chalk18.default.green(` \u2713 re-ran agent setup (${result.configured.join(", ") || "no changes"})`));
17859
+ console.log(import_chalk19.default.green(` \u2713 re-ran agent setup (${result.configured.join(", ") || "no changes"})`));
17718
17860
  if (result.warnings.length) {
17719
- console.log(import_chalk18.default.yellow(` notes: ${result.warnings.join("; ")}`));
17861
+ console.log(import_chalk19.default.yellow(` notes: ${result.warnings.join("; ")}`));
17720
17862
  }
17721
17863
  fixed++;
17722
17864
  } catch (err) {
17723
- console.log(import_chalk18.default.yellow(` ! could not re-run agent setup: ${err.message}`));
17865
+ console.log(import_chalk19.default.yellow(` ! could not re-run agent setup: ${err.message}`));
17724
17866
  }
17725
17867
  }
17726
- console.log(import_chalk18.default.dim("checking mcp server..."));
17868
+ console.log(import_chalk19.default.dim("checking mcp server..."));
17727
17869
  const claudeMcp = readMcpHyv(path18.join(claudeDesktopDir(), "claude_desktop_config.json"));
17728
17870
  const cursorMcp = readMcpHyv(path18.join(HOME, ".cursor", "mcp.json"));
17729
17871
  if (claudeMcp || cursorMcp) {
17730
17872
  if (claudeMcp)
17731
- console.log(import_chalk18.default.green(" \u2713 mcp configured for claude desktop"));
17873
+ console.log(import_chalk19.default.green(" \u2713 mcp configured for claude desktop"));
17732
17874
  if (cursorMcp)
17733
- console.log(import_chalk18.default.green(" \u2713 mcp configured for cursor"));
17875
+ console.log(import_chalk19.default.green(" \u2713 mcp configured for cursor"));
17734
17876
  } else {
17735
- console.log(import_chalk18.default.yellow(" ! mcp not configured \u2014 run: hyv doctor --fix-agents or hyv mcp --setup"));
17877
+ console.log(import_chalk19.default.yellow(" ! mcp not configured \u2014 run: hyv doctor --fix-agents or hyv mcp --setup"));
17736
17878
  issues++;
17737
17879
  }
17738
17880
  try {
17739
17881
  const stdio = await testMcpStdioSubprocess();
17740
17882
  if (stdio.ok && (stdio.toolCount || 0) >= 10) {
17741
- console.log(import_chalk18.default.green(` \u2713 mcp stdio subprocess healthy (${stdio.toolCount} tools)`));
17883
+ console.log(import_chalk19.default.green(` \u2713 mcp stdio subprocess healthy (${stdio.toolCount} tools)`));
17742
17884
  } else if (stdio.ok) {
17743
- console.log(import_chalk18.default.yellow(` ! mcp stdio ok but only ${stdio.toolCount || 0} tools`));
17885
+ console.log(import_chalk19.default.yellow(` ! mcp stdio ok but only ${stdio.toolCount || 0} tools`));
17744
17886
  issues++;
17745
17887
  } else {
17746
- console.log(import_chalk18.default.red(" \u2717 mcp stdio subprocess failed"));
17747
- console.log(import_chalk18.default.dim(" run: hyv mcp --test"));
17888
+ console.log(import_chalk19.default.red(" \u2717 mcp stdio subprocess failed"));
17889
+ console.log(import_chalk19.default.dim(" run: hyv mcp --test"));
17748
17890
  issues++;
17749
17891
  }
17750
17892
  } catch (err) {
17751
- console.log(import_chalk18.default.red(` \u2717 mcp stdio probe failed: ${err.message}`));
17893
+ console.log(import_chalk19.default.red(` \u2717 mcp stdio probe failed: ${err.message}`));
17752
17894
  issues++;
17753
17895
  }
17754
17896
  if (opts.verifyHosts) {
17755
- console.log(import_chalk18.default.dim("verifying mcp hosts (spawns subprocess per config)..."));
17897
+ console.log(import_chalk19.default.dim("verifying mcp hosts (spawns subprocess per config)..."));
17756
17898
  try {
17757
17899
  const pkgDir = path18.resolve(__dirname, "..");
17758
17900
  const { verifyAgentHosts } = require(path18.join(pkgDir, "scripts", "verify-agent-hosts.js"));
17759
17901
  const hosts = await verifyAgentHosts();
17760
17902
  for (const host of hosts) {
17761
17903
  if (host.kind === "manual") {
17762
- console.log(import_chalk18.default.yellow(` \u25CB ${host.label} \u2014 ${host.detail}`));
17904
+ console.log(import_chalk19.default.yellow(` \u25CB ${host.label} \u2014 ${host.detail}`));
17763
17905
  continue;
17764
17906
  }
17765
17907
  if (host.ok) {
17766
- console.log(import_chalk18.default.green(` \u2713 ${host.label}${host.detail ? ` (${host.detail})` : ""}`));
17908
+ console.log(import_chalk19.default.green(` \u2713 ${host.label}${host.detail ? ` (${host.detail})` : ""}`));
17767
17909
  } else if (host.kind === "file") {
17768
- console.log(import_chalk18.default.dim(` - ${host.label} \u2014 ${host.detail || "missing"}`));
17910
+ console.log(import_chalk19.default.dim(` - ${host.label} \u2014 ${host.detail || "missing"}`));
17769
17911
  } else {
17770
- console.log(import_chalk18.default.red(` \u2717 ${host.label} \u2014 ${host.detail || "failed"}`));
17912
+ console.log(import_chalk19.default.red(` \u2717 ${host.label} \u2014 ${host.detail || "failed"}`));
17771
17913
  issues++;
17772
17914
  }
17773
17915
  }
17774
17916
  } catch (err) {
17775
- console.log(import_chalk18.default.red(` \u2717 host verification failed: ${err.message}`));
17917
+ console.log(import_chalk19.default.red(` \u2717 host verification failed: ${err.message}`));
17776
17918
  issues++;
17777
17919
  }
17778
17920
  }
17779
17921
  console.log("");
17780
17922
  if (issues === 0 && fixed === 0) {
17781
- console.log(import_chalk18.default.green("\u2713 everything looks good!"));
17923
+ console.log(import_chalk19.default.green("\u2713 everything looks good!"));
17782
17924
  } else if (fixed > 0) {
17783
- console.log(import_chalk18.default.green(`\u2713 fixed ${fixed} issue(s)`));
17925
+ console.log(import_chalk19.default.green(`\u2713 fixed ${fixed} issue(s)`));
17784
17926
  if (issues > 0)
17785
- console.log(import_chalk18.default.yellow(`! ${issues} issue(s) remaining`));
17927
+ console.log(import_chalk19.default.yellow(`! ${issues} issue(s) remaining`));
17786
17928
  } else {
17787
- console.log(import_chalk18.default.yellow(`! ${issues} issue(s) found`));
17929
+ console.log(import_chalk19.default.yellow(`! ${issues} issue(s) found`));
17788
17930
  }
17789
- console.log(import_chalk18.default.dim("\nfree scan: hyv scan draft.md | full tour: hyv welcome\n"));
17931
+ console.log(import_chalk19.default.dim("\nfree scan: hyv scan draft.md | full tour: hyv welcome\n"));
17790
17932
  });
17791
17933
  }
17792
17934
 
17793
17935
  // src/commands/rename.ts
17794
- var import_chalk19 = __toESM(require_source());
17936
+ var import_chalk20 = __toESM(require_source());
17795
17937
  init_config();
17796
17938
  init_auth();
17797
17939
  function registerRenameCommand(program3) {
@@ -17799,26 +17941,26 @@ function registerRenameCommand(program3) {
17799
17941
  try {
17800
17942
  const trimmedName = newName.trim();
17801
17943
  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'));
17944
+ console.log(import_chalk20.default.red("\nerror: what do you want to name your profile?\n"));
17945
+ console.log(import_chalk20.default.dim(' example: hyv rename "my brand voice"\n'));
17804
17946
  process.exit(1);
17805
17947
  return;
17806
17948
  }
17807
17949
  if (trimmedName.length > 100) {
17808
- console.log(import_chalk19.default.red("\nerror: name is too long \u2014 keep it under 100 characters\n"));
17950
+ console.log(import_chalk20.default.red("\nerror: name is too long \u2014 keep it under 100 characters\n"));
17809
17951
  process.exit(1);
17810
17952
  return;
17811
17953
  }
17812
17954
  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"));
17955
+ console.log(import_chalk20.default.red("\nerror: name contains invalid characters\n"));
17956
+ console.log(import_chalk20.default.dim(" allowed: letters, numbers, spaces, hyphens, underscores, apostrophes\n"));
17815
17957
  process.exit(1);
17816
17958
  return;
17817
17959
  }
17818
17960
  const token = getToken();
17819
17961
  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"));
17962
+ console.log(import_chalk20.default.red("\nerror: you're not signed in yet\n"));
17963
+ console.log(import_chalk20.default.dim(" run: hyv init\n"));
17822
17964
  process.exit(1);
17823
17965
  return;
17824
17966
  }
@@ -17834,16 +17976,16 @@ function registerRenameCommand(program3) {
17834
17976
  );
17835
17977
  if (response.status === 200) {
17836
17978
  const data = response.data;
17837
- console.log(import_chalk19.default.green(`
17979
+ console.log(import_chalk20.default.green(`
17838
17980
  \u2713 profile renamed to ${data.profile?.name || trimmedName}
17839
17981
  `));
17840
17982
  } else {
17841
- console.log(import_chalk19.default.red(`
17983
+ console.log(import_chalk20.default.red(`
17842
17984
  error: server returned ${response.status}
17843
17985
  `));
17844
17986
  }
17845
17987
  } catch (error) {
17846
- console.error(import_chalk19.default.red(`
17988
+ console.error(import_chalk20.default.red(`
17847
17989
  error: ${error.message}
17848
17990
  `));
17849
17991
  process.exit(1);
@@ -17852,7 +17994,7 @@ error: ${error.message}
17852
17994
  }
17853
17995
 
17854
17996
  // src/commands/fix.ts
17855
- var import_chalk21 = __toESM(require_source());
17997
+ var import_chalk22 = __toESM(require_source());
17856
17998
  init_pipeline();
17857
17999
  init_local_profile();
17858
18000
  init_access();
@@ -17862,14 +18004,14 @@ init_config();
17862
18004
  var fs20 = __toESM(require("fs"));
17863
18005
  var path19 = __toESM(require("path"));
17864
18006
  var readline2 = __toESM(require("readline"));
17865
- var import_chalk20 = __toESM(require_source());
18007
+ var import_chalk21 = __toESM(require_source());
17866
18008
  async function confirmDestructiveWrite(options) {
17867
18009
  if (options.yes)
17868
18010
  return true;
17869
18011
  const label = options.target ? `${options.action} (${options.target})` : options.action;
17870
18012
  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"));
18013
+ console.error(import_chalk21.default.red("\nRefusing destructive write without confirmation (non-interactive)."));
18014
+ console.error(import_chalk21.default.dim(" Re-run with --yes to create .bak backups and proceed.\n"));
17873
18015
  return false;
17874
18016
  }
17875
18017
  const question = `
@@ -17905,9 +18047,9 @@ function registerFixCommand(program3) {
17905
18047
  if (options.format === "json") {
17906
18048
  console.log(JSON.stringify({ file: filePath, autoFixes: 0, llmIssues: result.stats.needsLLM, changes: [] }));
17907
18049
  } else {
17908
- console.log(import_chalk21.default.green("\n\u2713 No auto-fixable issues found."));
18050
+ console.log(import_chalk22.default.green("\n\u2713 No auto-fixable issues found."));
17909
18051
  if (result.stats.needsLLM > 0) {
17910
- console.log(import_chalk21.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
18052
+ console.log(import_chalk22.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
17911
18053
  }
17912
18054
  }
17913
18055
  return;
@@ -17921,16 +18063,16 @@ function registerFixCommand(program3) {
17921
18063
  fixed: options.dryRun ? void 0 : result.fixed
17922
18064
  }, null, 2));
17923
18065
  } else {
17924
- console.log(import_chalk21.default.dim(`
18066
+ console.log(import_chalk22.default.dim(`
17925
18067
  hyv fix ${filePath}
17926
18068
  `));
17927
18069
  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));
18070
+ 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
18071
  }
17930
- console.log(import_chalk21.default.green(`
18072
+ console.log(import_chalk22.default.green(`
17931
18073
  \u2713 ${result.changes.length} auto-fix${result.changes.length === 1 ? "" : "es"} applied`));
17932
18074
  if (result.stats.needsLLM > 0) {
17933
- console.log(import_chalk21.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
18075
+ console.log(import_chalk22.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
17934
18076
  }
17935
18077
  }
17936
18078
  if (!options.dryRun) {
@@ -17944,7 +18086,7 @@ hyv fix ${filePath}
17944
18086
  process.exit(1);
17945
18087
  }
17946
18088
  const backupPath = writeInPlaceWithBackup(filePath, result.fixed);
17947
- console.log(import_chalk21.default.dim(` Written to ${filePath} (backup: ${backupBasename(filePath)})`));
18089
+ console.log(import_chalk22.default.dim(` Written to ${filePath} (backup: ${backupBasename(filePath)})`));
17948
18090
  saveLastEditSession({
17949
18091
  original_path: filePath,
17950
18092
  edited_path: filePath,
@@ -17952,7 +18094,7 @@ hyv fix ${filePath}
17952
18094
  edited_text: result.fixed,
17953
18095
  profile: options.profile
17954
18096
  });
17955
- console.log(import_chalk21.default.dim(" Tip: hyv reinforce --last to teach your profile from this edit"));
18097
+ console.log(import_chalk22.default.dim(" Tip: hyv reinforce --last to teach your profile from this edit"));
17956
18098
  } else if (filePath === "stdin" || !options.inPlace) {
17957
18099
  process.stdout.write("\n" + result.fixed + "\n");
17958
18100
  if (filePath !== "stdin") {
@@ -17968,14 +18110,14 @@ hyv fix ${filePath}
17968
18110
  }
17969
18111
  await maybeShowLimitedModeHint(!!profile);
17970
18112
  } catch (error) {
17971
- console.error(import_chalk21.default.red(`Error: ${error.message}`));
18113
+ console.error(import_chalk22.default.red(`Error: ${error.message}`));
17972
18114
  process.exit(1);
17973
18115
  }
17974
18116
  });
17975
18117
  }
17976
18118
 
17977
18119
  // src/commands/check.ts
17978
- var import_chalk22 = __toESM(require_source());
18120
+ var import_chalk23 = __toESM(require_source());
17979
18121
  init_pipeline();
17980
18122
  init_local_profile();
17981
18123
  init_access();
@@ -17987,18 +18129,18 @@ function registerCheckCommand(program3) {
17987
18129
  if (text === "-") {
17988
18130
  const fs31 = require("fs");
17989
18131
  if (process.stdin.isTTY) {
17990
- console.error(import_chalk22.default.red("No input provided. Pipe content or pass text as argument."));
18132
+ console.error(import_chalk23.default.red("No input provided. Pipe content or pass text as argument."));
17991
18133
  process.exit(1);
17992
18134
  }
17993
18135
  inputText = fs31.readFileSync(0, "utf-8");
17994
18136
  }
17995
18137
  if (!inputText.trim()) {
17996
- console.error(import_chalk22.default.red("No text provided."));
18138
+ console.error(import_chalk23.default.red("No text provided."));
17997
18139
  process.exit(1);
17998
18140
  }
17999
18141
  const fs30 = require("fs");
18000
18142
  if (text !== "-" && fs30.existsSync(text)) {
18001
- console.log(import_chalk22.default.yellow(`"${text}" looks like a file. Did you mean: hyv scan ${text}`));
18143
+ console.log(import_chalk23.default.yellow(`"${text}" looks like a file. Did you mean: hyv scan ${text}`));
18002
18144
  process.exit(1);
18003
18145
  }
18004
18146
  const result = runPipeline(inputText, profile, false);
@@ -18022,30 +18164,30 @@ function registerCheckCommand(program3) {
18022
18164
  }, null, 2));
18023
18165
  } else {
18024
18166
  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`));
18167
+ console.log(import_chalk23.default.green("\n\u2713 Clean \u2014 no AI patterns found."));
18168
+ console.log(import_chalk23.default.dim(` score: ${result.score}/100`));
18027
18169
  } else {
18028
18170
  console.log("");
18029
18171
  printGroupedSignals(result.signalMap.signals.slice(0, 15), profile);
18030
18172
  if (result.signalMap.signals.length > 15) {
18031
- console.log(import_chalk22.default.dim(` ... and ${result.signalMap.signals.length - 15} more`));
18173
+ console.log(import_chalk23.default.dim(` ... and ${result.signalMap.signals.length - 15} more`));
18032
18174
  }
18033
- console.log(import_chalk22.default.yellow(`
18175
+ console.log(import_chalk23.default.yellow(`
18034
18176
  ${result.stats.totalSignals} issues (${result.stats.red} red, ${result.stats.yellow} yellow)`));
18035
- console.log(import_chalk22.default.dim(` score: ${result.score}/100`));
18177
+ console.log(import_chalk23.default.dim(` score: ${result.score}/100`));
18036
18178
  }
18037
18179
  await maybeShowLimitedModeHint(!!profile);
18038
18180
  }
18039
18181
  process.exit(result.stats.totalSignals > 0 ? 1 : 0);
18040
18182
  } catch (error) {
18041
- console.error(import_chalk22.default.red(`Error: ${error.message}`));
18183
+ console.error(import_chalk23.default.red(`Error: ${error.message}`));
18042
18184
  process.exit(1);
18043
18185
  }
18044
18186
  });
18045
18187
  }
18046
18188
 
18047
18189
  // src/commands/score.ts
18048
- var import_chalk23 = __toESM(require_source());
18190
+ var import_chalk24 = __toESM(require_source());
18049
18191
  init_pipeline();
18050
18192
  init_local_profile();
18051
18193
  function registerScoreCommand(program3) {
@@ -18070,14 +18212,14 @@ function registerScoreCommand(program3) {
18070
18212
  process.exit(1);
18071
18213
  }
18072
18214
  } catch (error) {
18073
- console.error(import_chalk23.default.red(`Error: ${error.message}`));
18215
+ console.error(import_chalk24.default.red(`Error: ${error.message}`));
18074
18216
  process.exit(1);
18075
18217
  }
18076
18218
  });
18077
18219
  }
18078
18220
 
18079
18221
  // src/commands/diff.ts
18080
- var import_chalk24 = __toESM(require_source());
18222
+ var import_chalk25 = __toESM(require_source());
18081
18223
  init_pipeline();
18082
18224
  init_local_profile();
18083
18225
  function registerDiffCommand(program3) {
@@ -18087,9 +18229,9 @@ function registerDiffCommand(program3) {
18087
18229
  const { text, path: filePath } = readText(file);
18088
18230
  const result = runPipeline(text, profile, true);
18089
18231
  if (result.changes.length === 0) {
18090
- console.log(import_chalk24.default.green("\n\u2713 No auto-fixable changes."));
18232
+ console.log(import_chalk25.default.green("\n\u2713 No auto-fixable changes."));
18091
18233
  if (result.stats.needsLLM > 0) {
18092
- console.log(import_chalk24.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite`));
18234
+ console.log(import_chalk25.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite`));
18093
18235
  }
18094
18236
  return;
18095
18237
  }
@@ -18104,42 +18246,42 @@ function registerDiffCommand(program3) {
18104
18246
  const originalLines = text.split("\n");
18105
18247
  const fixedLines = result.fixed.split("\n");
18106
18248
  const contextN = parseInt(options.context, 10);
18107
- console.log(import_chalk24.default.dim(`--- ${filePath}`));
18108
- console.log(import_chalk24.default.dim(`+++ ${filePath} (fixed)`));
18249
+ console.log(import_chalk25.default.dim(`--- ${filePath}`));
18250
+ console.log(import_chalk25.default.dim(`+++ ${filePath} (fixed)`));
18109
18251
  for (const change of result.changes) {
18110
18252
  const lineIdx = change.line - 1;
18111
18253
  const start = Math.max(0, lineIdx - contextN);
18112
18254
  const end = Math.min(originalLines.length, lineIdx + contextN + 1);
18113
- console.log(import_chalk24.default.dim(`@@ -${start + 1},${end - start} +${start + 1},${end - start} @@`));
18255
+ console.log(import_chalk25.default.dim(`@@ -${start + 1},${end - start} +${start + 1},${end - start} @@`));
18114
18256
  for (let i = start; i < end; i++) {
18115
18257
  if (i === lineIdx) {
18116
- console.log(import_chalk24.default.red(`-${originalLines[i]}`));
18117
- console.log(import_chalk24.default.green(`+${fixedLines[i]}`));
18258
+ console.log(import_chalk25.default.red(`-${originalLines[i]}`));
18259
+ console.log(import_chalk25.default.green(`+${fixedLines[i]}`));
18118
18260
  } else {
18119
- console.log(import_chalk24.default.dim(` ${originalLines[i]}`));
18261
+ console.log(import_chalk25.default.dim(` ${originalLines[i]}`));
18120
18262
  }
18121
18263
  }
18122
18264
  }
18123
- console.log(import_chalk24.default.green(`
18265
+ console.log(import_chalk25.default.green(`
18124
18266
  ${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`));
18267
+ console.log(import_chalk25.default.dim(` run: hyv fix ${file} -i to apply`));
18126
18268
  if (options.apply && filePath !== "stdin") {
18127
18269
  const fs30 = require("fs");
18128
18270
  const path27 = require("path");
18129
18271
  const backupPath = filePath + ".bak";
18130
18272
  fs30.copyFileSync(filePath, backupPath);
18131
18273
  fs30.writeFileSync(filePath, result.fixed);
18132
- console.log(import_chalk24.default.green(` \u2713 Applied. Backup: ${path27.basename(backupPath)}`));
18274
+ console.log(import_chalk25.default.green(` \u2713 Applied. Backup: ${path27.basename(backupPath)}`));
18133
18275
  }
18134
18276
  } catch (error) {
18135
- console.error(import_chalk24.default.red(`Error: ${error.message}`));
18277
+ console.error(import_chalk25.default.red(`Error: ${error.message}`));
18136
18278
  process.exit(1);
18137
18279
  }
18138
18280
  });
18139
18281
  }
18140
18282
 
18141
18283
  // src/commands/rules.ts
18142
- var import_chalk25 = __toESM(require_source());
18284
+ var import_chalk26 = __toESM(require_source());
18143
18285
  init_config();
18144
18286
  var RULE_CATALOG = [
18145
18287
  // AI Overused Words
@@ -18233,7 +18375,7 @@ function registerRulesCommand(program3) {
18233
18375
  for (const id of ids)
18234
18376
  disabledRules.delete(id);
18235
18377
  writeConfig({ ...config, disabled_rules: [...disabledRules] });
18236
- console.log(import_chalk25.default.green(`
18378
+ console.log(import_chalk26.default.green(`
18237
18379
  \u2713 Enabled: ${ids.join(", ")}`));
18238
18380
  return;
18239
18381
  }
@@ -18242,13 +18384,13 @@ function registerRulesCommand(program3) {
18242
18384
  for (const id of ids)
18243
18385
  disabledRules.add(id);
18244
18386
  writeConfig({ ...config, disabled_rules: [...disabledRules] });
18245
- console.log(import_chalk25.default.green(`
18387
+ console.log(import_chalk26.default.green(`
18246
18388
  \u2713 Disabled: ${ids.join(", ")}`));
18247
18389
  return;
18248
18390
  }
18249
18391
  if (options.reset) {
18250
18392
  writeConfig({ ...config, disabled_rules: [] });
18251
- console.log(import_chalk25.default.green("\n\u2713 All rules reset to default (enabled)"));
18393
+ console.log(import_chalk26.default.green("\n\u2713 All rules reset to default (enabled)"));
18252
18394
  return;
18253
18395
  }
18254
18396
  let rules = [...RULE_CATALOG];
@@ -18276,34 +18418,34 @@ function registerRulesCommand(program3) {
18276
18418
  }
18277
18419
  console.log("");
18278
18420
  for (const [cat, catRules] of categories) {
18279
- console.log(import_chalk25.default.bold(` ${cat} rules (${catRules.length})
18421
+ console.log(import_chalk26.default.bold(` ${cat} rules (${catRules.length})
18280
18422
  `));
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"));
18423
+ console.log(import_chalk26.default.dim(" ID Sev AutoFix Status"));
18424
+ 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
18425
  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");
18426
+ const sev = rule.severity === "red" ? import_chalk26.default.red("red") : import_chalk26.default.yellow("yel");
18427
+ const fix = rule.autoFixable ? import_chalk26.default.green(" \u2713") : import_chalk26.default.dim(" \u2717");
18428
+ const enabled2 = disabledRules.has(rule.id) ? import_chalk26.default.red(" \u2717 disabled") : import_chalk26.default.green(" \u2713 enabled");
18287
18429
  const id = rule.id.padEnd(24);
18288
- console.log(` ${import_chalk25.default.dim(id)} ${sev} ${fix} ${enabled2}`);
18430
+ console.log(` ${import_chalk26.default.dim(id)} ${sev} ${fix} ${enabled2}`);
18289
18431
  }
18290
18432
  console.log("");
18291
18433
  }
18292
18434
  const enabled = rules.filter((r) => !disabledRules.has(r.id)).length;
18293
18435
  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
18436
+ console.log(import_chalk26.default.dim(` ${rules.length} rules, ${enabled} enabled, ${disabled} disabled`));
18437
+ console.log(import_chalk26.default.dim(` toggle: hyv rules --disable <id>`));
18438
+ console.log(import_chalk26.default.dim(` reset: hyv rules --reset
18297
18439
  `));
18298
18440
  } catch (error) {
18299
- console.error(import_chalk25.default.red(`Error: ${error.message}`));
18441
+ console.error(import_chalk26.default.red(`Error: ${error.message}`));
18300
18442
  process.exit(1);
18301
18443
  }
18302
18444
  });
18303
18445
  }
18304
18446
 
18305
18447
  // src/commands/batch.ts
18306
- var import_chalk26 = __toESM(require_source());
18448
+ var import_chalk27 = __toESM(require_source());
18307
18449
  var fs21 = __toESM(require("fs"));
18308
18450
  var path20 = __toESM(require("path"));
18309
18451
  init_pipeline();
@@ -18312,13 +18454,13 @@ function registerBatchCommand(program3) {
18312
18454
  program3.command("batch").description("Scan or fix multiple files matching a glob").argument("<pattern>", 'Glob pattern (e.g., "posts/**/*.md")').option("--fix", "Apply auto-fixes (default: scan only)").option("-i, --in-place", "Write fixes back to files").option("-y, --yes", "Confirm destructive in-place fixes without prompting").option("--threshold <n>", "Fail if any file score < threshold").option("--fail-on-hit", "Exit with code 2 if any file has issues").option("--sort <field>", "Sort by: issues, score, name", "issues").option("--format <type>", "Output format (text, json, csv)", "text").option("--profile <name>", "Voice profile").option("--ignore <patterns>", "Comma-separated glob ignores").action(async (pattern, options) => {
18313
18455
  try {
18314
18456
  const profile = await loadProfileForCommand(options.profile);
18315
- const glob = require_index_min();
18316
- const files = glob.sync(pattern, {
18457
+ const { globSync } = require_index_min();
18458
+ const files = globSync(pattern, {
18317
18459
  ignore: options.ignore ? options.ignore.split(",") : void 0,
18318
18460
  nodir: true
18319
18461
  });
18320
18462
  if (files.length === 0) {
18321
- console.log(import_chalk26.default.yellow(`
18463
+ console.log(import_chalk27.default.yellow(`
18322
18464
  No files matching: ${pattern}`));
18323
18465
  return;
18324
18466
  }
@@ -18332,7 +18474,7 @@ No files matching: ${pattern}`));
18332
18474
  process.exit(1);
18333
18475
  }
18334
18476
  if (options.format === "text") {
18335
- console.log(import_chalk26.default.dim(`
18477
+ console.log(import_chalk27.default.dim(`
18336
18478
  scanning ${files.length} file${files.length === 1 ? "" : "s"}...
18337
18479
  `));
18338
18480
  }
@@ -18371,23 +18513,23 @@ No files matching: ${pattern}`));
18371
18513
  }
18372
18514
  } else {
18373
18515
  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");
18516
+ const icon = r.issues > 0 ? import_chalk27.default.red("\u25CF") : import_chalk27.default.green("\u25CB");
18517
+ 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);
18518
+ const issueStr = r.issues > 0 ? import_chalk27.default.red(`${r.issues} issues`) : import_chalk27.default.green("clean");
18377
18519
  console.log(` ${icon} ${r.file.padEnd(40)} ${issueStr.padEnd(20)} score: ${score}`);
18378
18520
  }
18379
18521
  const withIssues = results.filter((r) => r.issues > 0).length;
18380
18522
  const totalIssues = results.reduce((sum, r) => sum + r.issues, 0);
18381
18523
  const worst = results.reduce((min, r) => r.score < min.score ? r : min, results[0]);
18382
- console.log(import_chalk26.default.dim(`
18524
+ console.log(import_chalk27.default.dim(`
18383
18525
  \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`));
18526
+ console.log(import_chalk27.default.dim(` ${results.length} files, ${withIssues} with issues, ${totalIssues} total issues`));
18385
18527
  if (withIssues > 0) {
18386
- console.log(import_chalk26.default.dim(` worst: ${worst.file} (${worst.score}/100)`));
18528
+ console.log(import_chalk27.default.dim(` worst: ${worst.file} (${worst.score}/100)`));
18387
18529
  }
18388
18530
  if (options.fix && options.inPlace) {
18389
18531
  const fixed = results.filter((r) => r.autoFixes > 0);
18390
- console.log(import_chalk26.default.green(`
18532
+ console.log(import_chalk27.default.green(`
18391
18533
  \u2713 ${fixed.reduce((sum, r) => sum + r.autoFixes, 0)} auto-fixes applied across ${fixed.length} files`));
18392
18534
  }
18393
18535
  }
@@ -18399,14 +18541,14 @@ No files matching: ${pattern}`));
18399
18541
  if (belowThreshold)
18400
18542
  process.exit(1);
18401
18543
  } catch (error) {
18402
- console.error(import_chalk26.default.red(`Error: ${error.message}`));
18544
+ console.error(import_chalk27.default.red(`Error: ${error.message}`));
18403
18545
  process.exit(1);
18404
18546
  }
18405
18547
  });
18406
18548
  }
18407
18549
 
18408
18550
  // src/commands/watch.ts
18409
- var import_chalk27 = __toESM(require_source());
18551
+ var import_chalk28 = __toESM(require_source());
18410
18552
  var fs22 = __toESM(require("fs"));
18411
18553
  var path21 = __toESM(require("path"));
18412
18554
  init_pipeline();
@@ -18417,7 +18559,7 @@ function registerWatchCommand(program3) {
18417
18559
  const profile = await loadProfileForCommand(options.profile);
18418
18560
  const absPath = path21.resolve(file);
18419
18561
  if (!fs22.existsSync(absPath)) {
18420
- console.error(import_chalk27.default.red(`File not found: ${absPath}`));
18562
+ console.error(import_chalk28.default.red(`File not found: ${absPath}`));
18421
18563
  process.exit(1);
18422
18564
  }
18423
18565
  if (options.command === "fix") {
@@ -18429,10 +18571,10 @@ function registerWatchCommand(program3) {
18429
18571
  if (!confirmed)
18430
18572
  process.exit(1);
18431
18573
  }
18432
- console.log(import_chalk27.default.dim(`
18574
+ console.log(import_chalk28.default.dim(`
18433
18575
  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"));
18576
+ console.log(import_chalk28.default.dim(`command: ${options.command} debounce: ${options.debounce}ms`));
18577
+ console.log(import_chalk28.default.dim("ctrl+c to stop\n"));
18436
18578
  let debounceTimer = null;
18437
18579
  const debounceMs = parseInt(options.debounce, 10);
18438
18580
  let scanCount = 0;
@@ -18443,38 +18585,38 @@ watching ${absPath}`));
18443
18585
  const result = runPipeline(text, profile, options.command === "fix");
18444
18586
  scanCount++;
18445
18587
  const now = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false });
18446
- console.log(import_chalk27.default.dim(`[${now}] saved \u2014 ${options.command}ing...`));
18588
+ console.log(import_chalk28.default.dim(`[${now}] saved \u2014 ${options.command}ing...`));
18447
18589
  if (options.command === "score") {
18448
18590
  const score = result.score;
18449
- const color = score < 60 ? import_chalk27.default.red : score < 80 ? import_chalk27.default.yellow : import_chalk27.default.green;
18591
+ const color = score < 60 ? import_chalk28.default.red : score < 80 ? import_chalk28.default.yellow : import_chalk28.default.green;
18450
18592
  console.log(` ${color(score + "/100")}`);
18451
18593
  if (lastScore > 0 && score !== lastScore) {
18452
18594
  const delta = score - lastScore;
18453
- console.log(import_chalk27.default.dim(` ${delta > 0 ? "\u2191" : "\u2193"} ${Math.abs(delta)} from last scan`));
18595
+ console.log(import_chalk28.default.dim(` ${delta > 0 ? "\u2191" : "\u2193"} ${Math.abs(delta)} from last scan`));
18454
18596
  }
18455
18597
  lastScore = score;
18456
18598
  } else if (options.command === "fix") {
18457
18599
  if (result.changes.length > 0) {
18458
18600
  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));
18601
+ 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
18602
  }
18461
18603
  ignoreWatchUntil = Date.now() + debounceMs + 200;
18462
18604
  writeInPlaceWithBackup(absPath, result.fixed);
18463
- console.log(import_chalk27.default.green(` \u2713 ${result.changes.length} auto-fixes applied`));
18605
+ console.log(import_chalk28.default.green(` \u2713 ${result.changes.length} auto-fixes applied`));
18464
18606
  } else {
18465
- console.log(import_chalk27.default.green(" \u2713 no auto-fixable issues"));
18607
+ console.log(import_chalk28.default.green(" \u2713 no auto-fixable issues"));
18466
18608
  }
18467
18609
  } else {
18468
18610
  if (result.stats.totalSignals === 0) {
18469
- console.log(import_chalk27.default.green(` \u2713 clean \u2014 score: ${result.score}/100`));
18611
+ console.log(import_chalk28.default.green(` \u2713 clean \u2014 score: ${result.score}/100`));
18470
18612
  } else {
18471
- console.log(import_chalk27.default.yellow(` ${result.stats.totalSignals} issues (${result.stats.red} red, ${result.stats.yellow} yellow) score: ${result.score}/100`));
18613
+ console.log(import_chalk28.default.yellow(` ${result.stats.totalSignals} issues (${result.stats.red} red, ${result.stats.yellow} yellow) score: ${result.score}/100`));
18472
18614
  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");
18615
+ const sev = signal.severity === "red" ? import_chalk28.default.red("\u25CF") : import_chalk28.default.yellow("\u25CB");
18474
18616
  console.log(` ${sev} line ${signal.line}: ${signal.id} \u2014 ${signal.suggestion}`);
18475
18617
  }
18476
18618
  if (result.signalMap.signals.length > 3) {
18477
- console.log(import_chalk27.default.dim(` ... and ${result.signalMap.signals.length - 3} more`));
18619
+ console.log(import_chalk28.default.dim(` ... and ${result.signalMap.signals.length - 3} more`));
18478
18620
  }
18479
18621
  }
18480
18622
  }
@@ -18491,21 +18633,21 @@ watching ${absPath}`));
18491
18633
  debounceTimer = setTimeout(runScan, debounceMs);
18492
18634
  });
18493
18635
  process.on("SIGINT", () => {
18494
- console.log(import_chalk27.default.dim(`
18636
+ console.log(import_chalk28.default.dim(`
18495
18637
  ${scanCount} scans completed. exiting.`));
18496
18638
  process.exit(0);
18497
18639
  });
18498
18640
  await new Promise(() => {
18499
18641
  });
18500
18642
  } catch (error) {
18501
- console.error(import_chalk27.default.red(`Error: ${error.message}`));
18643
+ console.error(import_chalk28.default.red(`Error: ${error.message}`));
18502
18644
  process.exit(1);
18503
18645
  }
18504
18646
  });
18505
18647
  }
18506
18648
 
18507
18649
  // src/commands/demo.ts
18508
- var import_chalk28 = __toESM(require_source());
18650
+ var import_chalk29 = __toESM(require_source());
18509
18651
  var fs23 = __toESM(require("fs"));
18510
18652
  var SAMPLES = {
18511
18653
  linkedin: {
@@ -18596,52 +18738,52 @@ function registerDemoCommand(program3) {
18596
18738
  const style = options.clean ? "clean" : options.style;
18597
18739
  const sample = SAMPLES[style];
18598
18740
  if (!sample) {
18599
- console.error(import_chalk28.default.red(`Unknown style: ${options.style}. Valid: ${Object.keys(SAMPLES).filter((k2) => k2 !== "clean").join(", ")}`));
18741
+ console.error(import_chalk29.default.red(`Unknown style: ${options.style}. Valid: ${Object.keys(SAMPLES).filter((k2) => k2 !== "clean").join(", ")}`));
18600
18742
  process.exit(1);
18601
18743
  }
18602
18744
  if (options.output) {
18603
18745
  const outputPath = require("path").resolve(options.output);
18604
18746
  fs23.writeFileSync(outputPath, sample.text);
18605
- console.log(import_chalk28.default.green(`
18747
+ console.log(import_chalk29.default.green(`
18606
18748
  \u2713 Sample written to ${outputPath}`));
18607
18749
  if (sample.patterns.length > 0) {
18608
- console.log(import_chalk28.default.dim(` Contains ${sample.patterns.length} AI patterns: ${sample.patterns.slice(0, 5).join(", ")}...`));
18750
+ console.log(import_chalk29.default.dim(` Contains ${sample.patterns.length} AI patterns: ${sample.patterns.slice(0, 5).join(", ")}...`));
18609
18751
  }
18610
- console.log(import_chalk28.default.dim(`
18752
+ console.log(import_chalk29.default.dim(`
18611
18753
  Scan it: hyv scan ${options.output}`));
18612
- console.log(import_chalk28.default.dim(` Fix it: hyv fix ${options.output}`));
18754
+ console.log(import_chalk29.default.dim(` Fix it: hyv fix ${options.output}`));
18613
18755
  } else {
18614
- console.log(import_chalk28.default.bold(`
18756
+ console.log(import_chalk29.default.bold(`
18615
18757
  \u2500\u2500\u2500 sample (${style}) \u2500\u2500\u2500
18616
18758
  `));
18617
18759
  console.log(sample.text);
18618
- console.log(import_chalk28.default.dim(`
18760
+ console.log(import_chalk29.default.dim(`
18619
18761
  \u2500\u2500\u2500 end \u2500\u2500\u2500`));
18620
18762
  if (sample.patterns.length > 0) {
18621
- console.log(import_chalk28.default.dim(`
18763
+ console.log(import_chalk29.default.dim(`
18622
18764
  ${sample.patterns.length} AI patterns embedded: ${sample.patterns.slice(0, 8).join(", ")}...`));
18623
18765
  }
18624
- console.log(import_chalk28.default.dim(`
18766
+ console.log(import_chalk29.default.dim(`
18625
18767
  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
18768
+ console.log(import_chalk29.default.dim(` Scan it: hyv scan demo.md`));
18769
+ console.log(import_chalk29.default.dim(` Fix it: hyv fix demo.md
18628
18770
  `));
18629
18771
  }
18630
18772
  } catch (error) {
18631
- console.error(import_chalk28.default.red(`Error: ${error.message}`));
18773
+ console.error(import_chalk29.default.red(`Error: ${error.message}`));
18632
18774
  process.exit(1);
18633
18775
  }
18634
18776
  });
18635
18777
  }
18636
18778
 
18637
18779
  // src/commands/open.ts
18638
- var import_chalk29 = __toESM(require_source());
18780
+ var import_chalk30 = __toESM(require_source());
18639
18781
  var PAGES = {
18640
18782
  dashboard: "https://holdyourvoice.com/dashboard",
18641
18783
  profiles: "https://holdyourvoice.com/dashboard?tab=profiles",
18642
- pricing: "https://holdyourvoice.com/dashboard?tab=billing",
18784
+ pricing: "https://holdyourvoice.com/app/billing",
18643
18785
  settings: "https://holdyourvoice.com/dashboard",
18644
- billing: "https://holdyourvoice.com/dashboard?tab=billing"
18786
+ billing: "https://holdyourvoice.com/app/billing"
18645
18787
  };
18646
18788
  function registerOpenCommand(program3) {
18647
18789
  program3.command("open").description("Open the web dashboard in your browser").option("--page <path>", "Page: dashboard, profiles, pricing, settings", "dashboard").option("--profile <name>", "Deep-link to a specific profile").option("--no-browser", "Print URL only, don't open").action(async (options) => {
@@ -18653,12 +18795,12 @@ function registerOpenCommand(program3) {
18653
18795
  return;
18654
18796
  }
18655
18797
  const open3 = (await Promise.resolve().then(() => __toESM(require_open()))).default;
18656
- console.log(import_chalk29.default.dim(`
18798
+ console.log(import_chalk30.default.dim(`
18657
18799
  Opening ${url}...`));
18658
18800
  await open3(url);
18659
- console.log(import_chalk29.default.green(" \u2713 Opened in browser\n"));
18801
+ console.log(import_chalk30.default.green(" \u2713 Opened in browser\n"));
18660
18802
  } catch (error) {
18661
- console.error(import_chalk29.default.red(`Error: ${error.message}`));
18803
+ console.error(import_chalk30.default.red(`Error: ${error.message}`));
18662
18804
  process.exit(1);
18663
18805
  }
18664
18806
  });
@@ -18744,7 +18886,7 @@ function getWelcomeText(args2) {
18744
18886
  }
18745
18887
 
18746
18888
  // src/commands/content.ts
18747
- var import_chalk30 = __toESM(require_source());
18889
+ var import_chalk31 = __toESM(require_source());
18748
18890
  init_free_paid();
18749
18891
  var TEMPLATES = {
18750
18892
  cursor: {
@@ -18818,62 +18960,28 @@ ${COMMUNITY_URL}`
18818
18960
  function registerContentCommand(program3) {
18819
18961
  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
18962
  if (opts.list) {
18821
- console.log(import_chalk30.default.bold("\nhyv content templates\n"));
18963
+ console.log(import_chalk31.default.bold("\nhyv content templates\n"));
18822
18964
  for (const [key, t2] of Object.entries(TEMPLATES)) {
18823
- console.log(import_chalk30.default.dim(` ${key}`) + ` \u2014 ${t2.title}`);
18965
+ console.log(import_chalk31.default.dim(` ${key}`) + ` \u2014 ${t2.title}`);
18824
18966
  }
18825
18967
  console.log("");
18826
18968
  return;
18827
18969
  }
18828
18970
  const t = TEMPLATES[topic] || TEMPLATES.cursor;
18829
- console.log(import_chalk30.default.bold(`
18971
+ console.log(import_chalk31.default.bold(`
18830
18972
  ${t.title}
18831
18973
  `));
18832
18974
  console.log(t.body);
18833
- console.log(import_chalk30.default.dim("\nBlog: https://holdyourvoice.com/blog\n"));
18975
+ console.log(import_chalk31.default.dim("\nBlog: https://holdyourvoice.com/blog\n"));
18834
18976
  });
18835
18977
  }
18836
18978
 
18837
18979
  // src/commands/upgrade.ts
18838
- var import_chalk31 = __toESM(require_source());
18839
- var import_child_process4 = require("child_process");
18840
- init_version();
18980
+ init_billing_upgrade();
18841
18981
  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
- }
18982
+ 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) => {
18983
+ const plan = opts.plan === "multiple" ? "multiple" : "individual";
18984
+ await openBillingUpgrade({ plan });
18877
18985
  });
18878
18986
  }
18879
18987