Files
VoiceStudio/specs
Palash DebnathandClaude Opus 4.8 c37a932784 fix(voice-design): validator-safe instruct builder (plan-05, closes #114 #115) (#141)
* fix(voice-design): build validator-safe instruct on the frontend (#132)

plan-05 (option A — frontend guard). The engine validator is whitelist-strict
by design; the #114/#115 failures came from useTTS.js merging the free-text
instruct field with the category dropdowns, producing unsupported items (#115)
or two items in one category (#114).

- voiceInstruct.js buildDesignInstruct(vdStates, freeText): dropdowns win their
  category; free-text accepted only as a known tag in an open category;
  unknown/duplicate items are dropped and returned so the UI can warn. Derives
  TAG_TO_CATEGORY from CATEGORIES (single source of truth).
- useTTS.js design mode uses it instead of the raw merge; toasts dropped items.

Engine validator (_resolve_instruct) untouched — whitelist contract preserved,
no vendored-engine change.

Tests (TDD, vitest): voiceInstruct.test.js (6). Full frontend suite 72 passed;
typecheck + build green.

Closes #114, #115. Addresses #132.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(voice-design): split unsupported vs duplicate instruct; warn on dropdown drift (Greptile #141)

- buildDesignInstruct now returns { instruct, unsupported, duplicates }:
  `unsupported` = free-text prose (not a known tag, #115); `duplicates` = a
  valid tag whose category was already set (e.g. dropdown low pitch outranks a
  typed high pitch, #114). useTTS shows an accurate toast per bucket instead of
  calling a valid-but-outranked tag "unsupported".
- console.warn when a *dropdown* value isn't in CATEGORIES (option-list ↔
  whitelist drift) instead of silently dropping it.

Tests updated + 1 added (7/7); typecheck + build green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 11:12:36 +05:30
..