feat(voices): capped in-host voice menus, HD tier signalling, settings voice catalog (Patch A)#470
Merged
Merged
Conversation
…s voice catalog (Patch A) Implements the client-only slice of doc/plans/2026-07-02-voice-selection-ux.md: the catalog scales, the in-host menus never do. - New src/tts/VoiceCuration.ts: tier derivation from powered_by + price (no API change needed), popularity-ranked featured set (Coral/Nova/Ash/Onyx), gender-diverse HD pair, pin-current-first capped shortlists (Claude 6, Pi 5). - ClaudeVoiceMenu: shortlist cap + "More voices…" door (deep-links to the settings AI Chat tab), single [HD] chip replacing the raw credit chip, one muted footer line when tiers coexist, persisted pin so a stored voice never vanishes (and never tears down an open menu). - Pi menu: SayPi block capped with quiet HD suffix + door; Pi's built-in rows and PiVoiceSettings grid untouched; idempotent door; pin survives the addMissingPiVoices partial populate. - Settings AI Chat tab: full per-host voice catalog (HD/Everyday shelves, per-host selection, auth-aware empty state) — the door's destination. - openSettings(tab?) one-shot deep link via chrome.storage.local. Dormant-safe pre-flip: with today's single-tier catalogs there are no HD chips/footers; the only visible changes are the door rows and the settings catalog. Flip-day (20 voices on claude.ai) renders 6 rows + door instead of 20. Pre-release follow-up: run `npm run translate` for the 11 new en keys (requires translate-cli + OPENAI_API_KEY; English fallback until then). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_012DZR4Vp9B1RiKVrkfYiM1o
This was referenced Jul 2, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The voice catalog is about to grow 4–7x: 10 OpenAI voices are merged-and-dormant behind the API kill-switch (saypi-api #92/#215), and a third provider is under discussion (#305). On flip day, claude.ai's
/voicespayload becomes 20 voices — today's flat menu would render all of them, with raw credit chips (50/1k cr) as the only guidance. This PR implements Patch A of the voice-selection design (committed here, with its companion rollout plan): the catalog scales; the menu never does.What
src/tts/VoiceCuration.ts(new, pure, unit-tested) — tier derivation frompowered_by+ credits (no API change needed, per the rollout plan's confirmed contract), a popularity-ranked featured set for value voices (Coral, Nova, Ash, Onyx — from community/vendor-signal research; Alloy deliberately last), a gender-diverse HD pair, and pin-current-first capped shortlists. Ranking is keyed by voice id so a future server re-skin of display names (design §7.3) can't silently degrade curation.claude.ai menu — capped at 6 rows + a muted "More voices…" door that deep-links to the settings AI Chat tab. The raw credit chip is replaced by a single [HD] chip on premium rows plus one muted footer line ("HD voices use your monthly allowance about 20× faster"), both rendered only while tiers actually coexist. The user's stored voice is pinned first and can never vanish from the menu; the pin persists on the instance and is never applied by tearing down a menu the user has open.
pi.ai menu — the SayPi block is capped at 5 with a quiet
HDsuffix and the same door; Pi's native rows, its extra built-ins (voice7/8), and thePiVoiceSettingsgrid are untouched.Settings → AI Chat → Voices (new) — the door's destination: the full per-host catalog on HD/Everyday shelves with descriptions and per-host selection (explicit chatbot ids — the settings page resolves to
webotherwise), auth-aware empty states. Selections propagate to open host tabs via the existingvoicePreferencesstorage listener.openSettings(tab?)— one-shot deep link throughchrome.storage.local(content scripts can't reach the settings page's localStorage); no background changes.What you'll see today vs flip day
Pre-flip (single-tier catalogs) this is nearly dormant: no chips, no footer — just the door rows (claude.ai already serves 10 voices, so its menu tightens to 6 + door) and the new settings catalog. Flip day adds the HD signalling automatically.
Process
TDD fail-first throughout (58 new/updated assertions across 6 spec files, incl. the OpenAI + Claude catalog fixtures the rollout plan flagged as a gap). An 8-angle adversarial review pass found 7 correctness bugs pre-commit (door duplication, pin wiped by
addMissingPiVoices, pin re-render deleting Pi 7/8, open-menu teardown race, stale pins, wrong sign-in prompt for authed users, throw on malformed catalog entries) — each is fixed and pinned by a test.npm testfully green (tsc + Jest + Vitest, 1664 tests).Follow-ups (not in this PR)
npm run translatefor the 11 new_locales/enkeys (needstranslate-cli+OPENAI_API_KEY; English fallback until then).sample_url) + the meteredintroduceVoicefix — gated on the saypi-api asset pipeline (design §4).featured/recommended/sibling_id) — design §5; tier badges for thePiVoiceSettingsgrid.🤖 Generated with Claude Code
https://claude.ai/code/session_012DZR4Vp9B1RiKVrkfYiM1o