1---2name: voice-batch-runner3description: Generate and manage persona-aware voice assets for short-form video production, including voice design, script-specific audio takes, and future reusable voice identities. Use this when persona registries and scripts already exist and you need local audio assets, voice manifests, and reviewable voice iterations without losing continuity across many videos.4---56# Voice Batch Runner78## Use When9- Persona, concept, and script inputs already exist and the next step is hosted10 voice design, cloned voice take generation, or polling.11- The voice should remain a durable persona asset across scripts, not a one-off12 audio byproduct.1314## Do Not Use When15- The task belongs to ideation, QA, or another released skill listed in the handoff section.16- Required inputs are missing and guessing would change the result.17- Voice strategy, task class, translation policy, or lip-sync intent is still18 unresolved. Use `audio-generation` first.1920## Execution Boundary21- This runner validates and executes normalized voice requests. It must not make22 creative strategy, voice-policy, or reference-policy decisions.23- Separate the workflow into voice profile, optional voice identity, and concrete24 voice take. The script text can change; persona voice continuity should not.25- Voice design is for an initial persona-aligned sound from `text`,26 `voice_description`, and `language`.27- Voice clone is for new script takes when approved reference `audio` and an28 optional `reference_text` should preserve timbre and speaking style.2930## Source And Path31- Ground requests in the active project persona registry, voice baseline, script32 text, and video purpose/lane.33- Use the active project/client folder first; do not assume one client directory34 is the source base for all voice work.35- Keep internal request/response/run state under `.postplus` when it is not the36 user-facing handoff. Keep final audio and review files in the active voice37 asset folder, or state the chosen workspace path.3839## Request Boundary40- Voice design synthesizes a persona voice from spoken `text`, a free-text41 `voice_description`, and an optional `language` (defaults to auto).42- Voice clone reproduces an approved voice from spoken `text`, an `audio`43 reference, an optional `reference_text` transcript, and optional `language`.44 Pass a local path, HTTPS URL, existing PostPlus media reference, or data URI45 directly to `--audio`. The CLI validates and prepares local media before the46 single hosted submit; do not pre-upload it or construct a manual request.47- Exact field names, requiredness, and defaults are discovered from48 `postplus media schema --json` and the generated example below; do not hard-code49 a private request envelope here.5051## Review And Handoff52- Before generation, verify persona registry, voice baseline, script stability,53 route (`voice_design` or `voice_clone_take`), source basis, and output path.54- After generation, review realism, persona fit, pacing, ad-like delivery,55 reuse potential, and for cloned output, timbre/accent drift from the reference.56- If pending, return the manifest path, the `output.data.id`57 generation handle, and the poll command58 `postplus media poll --handle <output.data.id>`. The poll waits in-command59 (up to 45s per invocation, checking every 8s); rerun it while pending60 instead of writing a tighter retry loop.61- Save a finished take with `postplus media-file download`, using the completed62 result's artifact reference when present or its output URL otherwise.6364## Stop Conditions65- Stop when required user intent, source evidence, or owned input artifacts are66 missing and guessing would change the result.67- If an owned CLI or script command fails, report the exact error and stop. Do68 not bypass the failure with metadata-only answers, readiness probing, local69 payload rewrites, alternate execution paths, or unpublished tools.70- Batch isolation: when producing a batch of independent items, a per-item71 content/safety rejection is isolated to that item. It is identified72 only by the typed code `postplus_cli_hosted_media_content_policy_blocked`,73 never by matching error prose, and it surfaces at either boundary: a failed74 `postplus media create` whose typed error `code` is that code, or a75 submitted run whose poll result carries `output.data.status: failed` and76 `output.data.error.code` set to that code. On either, record which item was77 blocked and its exact reason, skip it, and continue submitting and polling78 the remaining items, then report the incomplete set at the end. Do not retry,79 soften, or re-submit the blocked item — that is a forbidden payload rewrite.80 Every other failure (a failed owned CLI/script command whose typed `code` is81 not that content-policy code, or a run whose `error.code` is not that82 content-policy code — auth, transport, quota, malformed request, service83 outage) is systemic: stop per the rule above.8485## Public Command Boundary8687- Choose the smallest matching command or workflow from the user input and run88 it directly.89- Readiness diagnostics: `postplus doctor --skill voice-batch-runner`.90- Poll a pending voice take: `postplus media poll --handle <output.data.id>`91 (waits in-command up to 45s per invocation; rerun while pending).92- If an owned CLI or script command fails, report the exact error and stop. Do93 not bypass the failure with metadata-only answers, readiness probing, local94 payload rewrites, alternate execution paths, or unpublished tools.95- Use `postplus media schema --json` only when constructing or repairing an unknown request shape.96- Run the hosted submit with the generated command below; do not use another execution interface.9798<!-- BEGIN GENERATED EXECUTION EXAMPLE -->99```bash100postplus media create voice-design \101 --text "example text" \102 --voice-description "example voice_description" \103 --wait \104 --output ./result.json105```106<!-- END GENERATED EXECUTION EXAMPLE -->107108- If the CLI returns a quote-confirmation challenge, run `postplus quote confirm --json --challenge-file <challenge.json>` and retry with the returned token.