@holdyourvoice/hyv 2.9.6 → 2.9.8

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  All notable CLI changes. Also mirrored to [holdyourvoice.com/changelog](https://holdyourvoice.com/changelog) for user-facing releases.
4
4
 
5
+ ## [2.9.7] — 2026-06-12
6
+
7
+ ### Fixed
8
+ - `hyv sync` — profiles with spaces or missing slugs (e.g. "Say About Us") no longer crash with "Invalid profile name"
9
+ - Welcome step 4 — clearer sync failure messages (HTTP status / server error)
10
+
11
+ ## [2.9.6] — 2026-06-12
12
+
13
+ ### Fixed
14
+ - Welcome profile sync — server accepts `content` markdown from step 4 (upsert, no duplicate-profile 403)
15
+ - Dashboard handoff — opens `/app/billing` with session cookie; falls back to billing URL if handoff fails
16
+ - Edge worker handles `/cli/auth/web-handoff` (no container lag)
17
+
18
+ ### Changed
19
+ - `hyv open dashboard` and paid-feature copy point to `/app` not `/dashboard`
20
+
5
21
  ## [2.9.5] — 2026-06-12
6
22
 
7
23
  ### Fixed
package/dist/index.js CHANGED
@@ -4680,6 +4680,10 @@ function assertSafeProfileName(name) {
4680
4680
  }
4681
4681
  return normalized;
4682
4682
  }
4683
+ function toSafeProfileCacheKey(name) {
4684
+ const normalized = String(name || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
4685
+ return assertSafeProfileName(normalized || "profile");
4686
+ }
4683
4687
  function profilePathForName(name) {
4684
4688
  const safe = assertSafeProfileName(name);
4685
4689
  ensureHyvDir();
@@ -15730,7 +15734,8 @@ function registerSyncCommand(program3) {
15730
15734
  ensureHyvDir();
15731
15735
  let profileCount = 0;
15732
15736
  for (const profile of data.profiles) {
15733
- writeCachedProfile(profile.slug || profile.name, profile.content);
15737
+ const cacheKey = toSafeProfileCacheKey(profile.slug || profile.name);
15738
+ writeCachedProfile(cacheKey, profile.content);
15734
15739
  profileCount++;
15735
15740
  }
15736
15741
  const rulesPath = path7.join(CACHE_DIR, "rules.md");
@@ -15743,7 +15748,8 @@ function registerSyncCommand(program3) {
15743
15748
  }
15744
15749
  for (const profile of data.profiles) {
15745
15750
  try {
15746
- await loadFullProfile(profile.slug || profile.name, { forceRefresh: true });
15751
+ const cacheKey = toSafeProfileCacheKey(profile.slug || profile.name);
15752
+ await loadFullProfile(cacheKey, { forceRefresh: true });
15747
15753
  } catch {
15748
15754
  }
15749
15755
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holdyourvoice/hyv",
3
- "version": "2.9.6",
3
+ "version": "2.9.8",
4
4
  "description": "Free local AI writing scan for cursor & claude. MCP server, 220+ pattern detection, voice profiles. npx @holdyourvoice/hyv welcome",
5
5
  "main": "dist/index.js",
6
6
  "bin": {