The clone server passed instruct=voice_cfg.get("instruct") at both call sites,
so a voice's delivery was fixed in voices.json for its whole lifetime. For an
audiobook that means a character can be consistent or expressive, not both:
VoiceDesign takes a per-request instruct but has no seed, so its identity is
re-sampled on every call, while VoiceClone is deterministic but had no way to
direct a line.
SpeechRequest now accepts instruct, merged identity-first via _merge_instruct()
— the voice's own description followed by the line's direction — so directing
one line cannot re-roll the character. Same rule run_voicedesign_server.py got
in v6.8.
This is safe on the clone path specifically because extract_embeddings.py writes
full ICL prompts (ref codec tokens + ref_text), not x-vector-only ones;
model.py warns that instruct is unreliable in the latter mode.
The change lives in patches/openai_server.patch, regenerated against the
pristine upstream blob and verified to apply cleanly. README documents the
request field and adds a section on the cast-in-VoiceDesign,
narrate-from-VoiceClone workflow.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>