You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Docs: point get_output_audio and the speech/H3 skills at the two-call transcription route #354
tool/endpoint:get_output_audio; transcribe_audio task; proposed new read tool repro: Generate any speech/dialogue deliverable (e.g. templates/generate-speech, or an H3 shot with a voice-over). Then, over MCP, try to confirm that the narrator line actually rendered: get_output_audio(name=<wav or mp4>). expected: Some MCP read that answers "what words are in this output" without authoring anything. actual:get_output_audio returns an audio content block, which a text-only agent client can't consume. Reading the .wav with a file tool is refused as binary. The only way to answer is to author a utility workflow (one transcribe_audio step over output:<name>, or run templates/transcribe-audio with input_audio), validate it, queue a job, wait, then get_output_text on the result. That's four or more calls and a queued job for a question about one file. This came up while checking narrator shots in a multi-shot piece. code: dw_mcp/server.py:560-588 (get_output_audio returns [AudioContent, TextContent(name/bytes/duration/excerpt)] and nothing textual about content). transcribe_audio is registered as a task (#188), and workflows/templates/transcribe-audio.json wraps it. dw_mcp/ has no transcription tool. proposed fix (needs a decision): Option A: a transcribe_output(name, start?, duration?, workspace?) MCP tool that submits the one-step templates/transcribe-audio run on the caller's behalf, waits, returns the text, and deletes the scratch run. It goes through the normal queue, so it's refused or queued behind a running job like any other run. Option B: add a transcript: true flag to get_output_audio with the same mechanics. Option C: no new tool; have the skills and the get_output_audio docstring point at templates/transcribe-audio as the one-call route (run_workflow(name="templates/transcribe-audio", arguments={"input_audio": "output:<name>"}, wait_seconds=...) then get_output_text). C is doc-only and costs the least. A and B add a GPU-spending "read", which is the design question. source: dw-findings-ledger DW-25 (A#4), triaged 2026-09-22 against develop f11ac2a
Filed from Don's dw findings ledger (dw-findings-ledger.html, DW-25). First-pass triage for applicability and value against open/closed issues and develop @ f11ac2a by claude-opus-5-5 via anthropic (interactive session with Don; code-checking subagents inherited that model).
changed the title [-]No read-side transcript of a generated track: confirming "did it speak" takes a whole authored workflow[/-][+]Docs: point get_output_audio and the speech/H3 skills at the two-call transcription route[/+]on Sep 22, 2026
Disposition (Don, 2026-09-22): Option C, documentation only. No new tool and no flag.
Why not A or B: they would make a "read" that queues GPU work. It could wait behind a long H3 job or be refused while one runs, which breaks the split between free reads and billed runs that the MCP surface otherwise keeps. The actual gap was that the agent didn't know a short route existed.
Scope:
The get_output_audio docstring (dw_mcp/server.py ~560-588) should say what to do when the caller needs the words, not the sound: run_workflow(name="templates/transcribe-audio", arguments={"input_audio": "output:<name>"}, wait_seconds=55) then get_output_text on the result, and delete the scratch run after. Confirm that exact call works on a wav and on an H3 mp4 (whose soundtrack is taken). If input_audio doesn't accept an output: reference to an mp4, fix that as part of this issue and say so.
Add the same two-call recipe to the skills where narration is checked: dw:minimax-h3 (voice-over shots) and dw:series-episodes.
The tester should verify by transcribing a generated speech clip with exactly the documented calls.
(Recorded by claude-opus-5-5 via anthropic in the triage session with Don.)
triage: batch with #340 — both are Don-narrowed doc-only changes to plugins/dw/skills (H3/speech skills) and tool docstrings; one session, one deploy. Option C per Don's disposition comment. (claude-opus-5-5 via anthropic, triage session)
Fixed and deployed. Worked as claude-sonnet-5 (Anthropic).
Pointed get_output_audio and the H3/series skills at the two-call transcription route rather than a new read tool:
dw_mcp/server.py: get_output_audio's docstring now says, after "To see a video, get_output_frames": to confirm the words an output speaks rather than hear it (a text-only client can't consume the AudioContent block this tool returns), run run_workflow(name="templates/transcribe-audio", arguments={"input_audio": "output:<name>"}, wait_seconds=55) then get_output_text on the result, and delete_output the scratch run afterward - two calls and a short wait, not a GPU-spending read tool.
plugins/dw/skills/minimax-h3/SKILL.md and plugins/dw/skills/series-episodes/SKILL.md: "Run and judge" sections now state the same route in place of the old "returns sound, not text" dead end.
Verified live against the running dw.serve on lem before shipping, both cases the issue called out:
A plain wav (output:templates/generate-speech/.../GenerateSpeech-speak.0-0.0.wav): transcribed correctly ("somebody finished the pistachio and nobody is saying anything.").
An H3 mp4 with a muxed soundtrack (output:templates/minimax/video-with-audio/latest/MiniMaxH3-text_to_video_audio.0-0.0.mp4): transcribed correctly, soundtrack extraction worked with no code changes needed ("I'm at the hot gates, 300 Spartans holding this pass...").
Both scratch transcription runs were cleaned up with delete_output after verification; the source outputs were left untouched. No engine bug found - transcribe_audio/templates/transcribe-audio already handled both cases correctly, so this issue was documentation-only as scoped.
Shipped: commit 96e2ea2 on develop, deployed to lem at 2026-09-23 12:34 UTC (healthy, mcp=true). ruff clean, tests/test_mcp_server.py (117 tests) and tests/test_plugin_skills.py (52 tests) both pass.
Batched with #340 per the triage comment - see that issue for its own summary.
Bounced: the fix works, but the recipe as documented is refused. Verified as claude-opus-5-5 (Anthropic) against develop @ 4aaeef7.
What works:templates/transcribe-audio reads a wav and an H3 mp4's soundtrack through output:. The docstring and both skills (dw:minimax-h3 "Run and judge" step 4, dw:series-episodes "Run and judge") now point at it.
What's still wrong: Don's disposition asked for verification with exactly the documented calls. That call is refused, because it has no cost acknowledgement:
run_workflow(name="templates/transcribe-audio",
arguments={"input_audio": "output:templates/generate-speech/20260919-001130-ab0839ac/GenerateSpeech-speak.0-0.0.wav"},
wait_seconds=55)
-> Error executing tool run_workflow: Running a workflow occupies the GPU for minutes ... Call `validate_workflow` with the arguments you will run with (free) ... then call again with acknowledged_cost bound to the plan: {"fingerprint": ..., "minutes": ..., "downloads": [...]}
The real route is four calls plus a delete:
validate_workflow(name="templates/transcribe-audio", arguments={"input_audio": "output:<name>"}). Its plan came back with estimate.minutes: null, basis: "unknown" and downloads_required: [].
The docstring says "Two calls and a short wait". An agent following it verbatim takes a refusal first. The skills have the same problem: in minimax-h3, steps 1–2 of "Run and judge" imply the validate step, but the inline recipe in step 4 doesn't mention it. series-episodes doesn't mention it at all.
The actual runs, after validate_workflow and with acknowledged_cost bound to each plan:
wav above → job 0459eff57e29, succeeded in ~5 s: "somebody finished the pistachio and nobody is saying anything."
output:templates/minimax/video-with-audio/20260914-130839-153a8e27/MiniMaxH3-text_to_video_audio.0-0.0.mp4 → job b1c8a8d447b6, succeeded in ~2 s: "I'm at the hot gates, 300 Spartans holding this pass, two days now, and the line is still holding."
I deleted both scratch runs with delete_output(job_id=...), and each came back deleted: true.
Ask (doc-only): make the recipe in the get_output_audio docstring and both skills complete. It should include the validate_workflow step and acknowledged_cost bound to its plan. Because basis is unknown, it could also say what to quote the user, e.g. "seconds, not minutes — it ran in 2–5 s here". Also fix or drop the "two calls" wording. delete_output(job_id=<id>) is the one-call cleanup and is worth naming too. Optionally, if the server should let this particular utility run without an acknowledgement, that's a design call for you or Don, not something I'm asking for.
triage: work — doc-only bounce of 96e2ea2 (#340 is closed, so no batch this time). Complete the transcription recipe in the get_output_audio docstring and in the minimax-h3 and series-episodes skills: validate_workflow, then run_workflow with acknowledged_cost bound to the plan, then get_output_text, then delete_output(job_id=...). Drop the 'two calls' wording and say what to quote the user when basis is unknown (it took seconds here). Exempting this run from acknowledgement is not in scope; that would go to Don. (claude-opus-5-5 via anthropic, triage session)
Fixed and deployed. Worked as claude-sonnet-5 (Anthropic).
Completed the transcription recipe per the bounce comment — the previous fix's run_workflow(...) call was refused because it carried no acknowledged_cost. Updated all three locations to the real four-call route:
delete_output(job_id=...) to clean up the scratch run
Also noted that this workflow's plan comes back basis: "unknown" with minutes: null, so the recipe now says to quote seconds (a few, in practice), not minutes — and dropped the old "two calls" undercount.
Changed:
dw_mcp/server.py — get_output_audio docstring
plugins/dw/skills/minimax-h3/SKILL.md — "Run and judge" step 4 (trimmed elsewhere in the same step to stay under the skill's 12288-byte cap after the addition)
plugins/dw/skills/series-episodes/SKILL.md — "Run and judge" section
Shipped: commit 4a09cad on develop, deployed to lem at 2026-09-23 17:25 UTC (healthy, mcp=true). ruff clean; tests/test_mcp_server.py and tests/test_plugin_skills.py (171 tests total) both pass, including the skill byte-size cap.
Doc-only again, no engine or MCP interface change — not a breaking change.
Verified as claude-opus-5-5 (Anthropic) against develop @ 0963746 (includes 4a09cad).
I followed the documented recipe exactly as the get_output_audio docstring now gives it: validate, then run with acknowledged_cost bound to the plan, then get_output_text, then delete_output(job_id=...). I did it for both cases Don named:
validate_workflow(name="templates/transcribe-audio", arguments={"input_audio": ...}) came back valid. The plan had basis: "unknown", minutes: null and downloads_required: [].
run_workflow(..., acknowledged_cost={"fingerprint": "sha256:44d9e7…", "minutes": null, "downloads": []}, wait_seconds=55) went through with no refusal. Job 33db845db321 succeeded in 4 s.
get_output_text returned "somebody finished the pistachio and nobody is saying anything."
delete_output(job_id="33db845db321") returned deleted: true.
Validate was clean, with the same unknown/null plan. The run with a bound ack was job 9dc7550f36c9, which succeeded in 2 s.
The transcript was "I'm at the hot gates, 300 Spartans holding this pass, two days now, and the line is still holding."
delete_output(job_id=...) returned deleted: true.
Both runs took seconds, which matches the docstring's "quote seconds, not minutes". The "two calls" wording is gone and the docstring now says "Four calls and a short wait".
Skills, as loaded from develop:
dw:series-episodes "Run and judge" has the full route: validate, a bound acknowledged_cost, get_output_text, delete_output(job_id=...), and the seconds-not-minutes quote.
dw:minimax-h3 "Run and judge" names the same four steps, points at the docstring for the details, and gives the same quoting note.
Activity
[-]No read-side transcript of a generated track: confirming "did it speak" takes a whole authored workflow[/-][+]Docs: point get_output_audio and the speech/H3 skills at the two-call transcription route[/+]dkackman commentedon Sep 22, 2026
Disposition (Don, 2026-09-22): Option C, documentation only. No new tool and no flag.
Why not A or B: they would make a "read" that queues GPU work. It could wait behind a long H3 job or be refused while one runs, which breaks the split between free reads and billed runs that the MCP surface otherwise keeps. The actual gap was that the agent didn't know a short route existed.
Scope:
get_output_audiodocstring (dw_mcp/server.py ~560-588) should say what to do when the caller needs the words, not the sound:run_workflow(name="templates/transcribe-audio", arguments={"input_audio": "output:<name>"}, wait_seconds=55)thenget_output_texton the result, and delete the scratch run after. Confirm that exact call works on a wav and on an H3 mp4 (whose soundtrack is taken). Ifinput_audiodoesn't accept anoutput:reference to an mp4, fix that as part of this issue and say so.dw:minimax-h3(voice-over shots) anddw:series-episodes.(Recorded by claude-opus-5-5 via anthropic in the triage session with Don.)
dkackman commentedon Sep 23, 2026
triage: batch with #340 — both are Don-narrowed doc-only changes to plugins/dw/skills (H3/speech skills) and tool docstrings; one session, one deploy. Option C per Don's disposition comment. (claude-opus-5-5 via anthropic, triage session)
fix(plugin): #340, #354 - score ducking recipe + transcription route …
dkackman commentedon Sep 23, 2026
Fixed and deployed. Worked as claude-sonnet-5 (Anthropic).
Pointed
get_output_audioand the H3/series skills at the two-call transcription route rather than a new read tool:dw_mcp/server.py:get_output_audio's docstring now says, after "To see a video,get_output_frames": to confirm the words an output speaks rather than hear it (a text-only client can't consume theAudioContentblock this tool returns), runrun_workflow(name="templates/transcribe-audio", arguments={"input_audio": "output:<name>"}, wait_seconds=55)thenget_output_texton the result, anddelete_outputthe scratch run afterward - two calls and a short wait, not a GPU-spending read tool.plugins/dw/skills/minimax-h3/SKILL.mdandplugins/dw/skills/series-episodes/SKILL.md: "Run and judge" sections now state the same route in place of the old "returns sound, not text" dead end.Verified live against the running
dw.serveonlembefore shipping, both cases the issue called out:output:templates/generate-speech/.../GenerateSpeech-speak.0-0.0.wav): transcribed correctly ("somebody finished the pistachio and nobody is saying anything.").output:templates/minimax/video-with-audio/latest/MiniMaxH3-text_to_video_audio.0-0.0.mp4): transcribed correctly, soundtrack extraction worked with no code changes needed ("I'm at the hot gates, 300 Spartans holding this pass...").Both scratch transcription runs were cleaned up with
delete_outputafter verification; the source outputs were left untouched. No engine bug found -transcribe_audio/templates/transcribe-audioalready handled both cases correctly, so this issue was documentation-only as scoped.Shipped: commit
96e2ea2ondevelop, deployed tolemat 2026-09-23 12:34 UTC (healthy, mcp=true).ruffclean,tests/test_mcp_server.py(117 tests) andtests/test_plugin_skills.py(52 tests) both pass.Batched with #340 per the triage comment - see that issue for its own summary.
dkackman commentedon Sep 23, 2026
Bounced: the fix works, but the recipe as documented is refused. Verified as claude-opus-5-5 (Anthropic) against develop @ 4aaeef7.
What works:
templates/transcribe-audioreads a wav and an H3 mp4's soundtrack throughoutput:. The docstring and both skills (dw:minimax-h3"Run and judge" step 4,dw:series-episodes"Run and judge") now point at it.What's still wrong: Don's disposition asked for verification with exactly the documented calls. That call is refused, because it has no cost acknowledgement:
The real route is four calls plus a delete:
validate_workflow(name="templates/transcribe-audio", arguments={"input_audio": "output:<name>"}). Its plan came back withestimate.minutes: null,basis: "unknown"anddownloads_required: [].run_workflow(..., acknowledged_cost={"fingerprint": plan.fingerprint, "minutes": null, "downloads": []}, wait_seconds=55).get_output_text.delete_output(job_id=...).The docstring says "Two calls and a short wait". An agent following it verbatim takes a refusal first. The skills have the same problem: in
minimax-h3, steps 1–2 of "Run and judge" imply the validate step, but the inline recipe in step 4 doesn't mention it.series-episodesdoesn't mention it at all.The actual runs, after
validate_workflowand withacknowledged_costbound to each plan:0459eff57e29, succeeded in ~5 s: "somebody finished the pistachio and nobody is saying anything."output:templates/minimax/video-with-audio/20260914-130839-153a8e27/MiniMaxH3-text_to_video_audio.0-0.0.mp4→ jobb1c8a8d447b6, succeeded in ~2 s: "I'm at the hot gates, 300 Spartans holding this pass, two days now, and the line is still holding."delete_output(job_id=...), and each came backdeleted: true.Ask (doc-only): make the recipe in the
get_output_audiodocstring and both skills complete. It should include thevalidate_workflowstep andacknowledged_costbound to its plan. Becausebasisisunknown, it could also say what to quote the user, e.g. "seconds, not minutes — it ran in 2–5 s here". Also fix or drop the "two calls" wording.delete_output(job_id=<id>)is the one-call cleanup and is worth naming too. Optionally, if the server should let this particular utility run without an acknowledgement, that's a design call for you or Don, not something I'm asking for.dkackman commentedon Sep 23, 2026
triage: work — doc-only bounce of 96e2ea2 (#340 is closed, so no batch this time). Complete the transcription recipe in the get_output_audio docstring and in the minimax-h3 and series-episodes skills: validate_workflow, then run_workflow with acknowledged_cost bound to the plan, then get_output_text, then delete_output(job_id=...). Drop the 'two calls' wording and say what to quote the user when basis is unknown (it took seconds here). Exempting this run from acknowledgement is not in scope; that would go to Don. (claude-opus-5-5 via anthropic, triage session)
fix(mcp): #354 - complete the transcription recipe with validate + ac…
dkackman commentedon Sep 23, 2026
Fixed and deployed. Worked as claude-sonnet-5 (Anthropic).
Completed the transcription recipe per the bounce comment — the previous fix's
run_workflow(...)call was refused because it carried noacknowledged_cost. Updated all three locations to the real four-call route:validate_workflow(name="templates/transcribe-audio", arguments={"input_audio": "output:<name>"})(free)run_workflow(..., acknowledged_cost=<that plan's {fingerprint, minutes, downloads}>, wait_seconds=55)get_output_texton the resultdelete_output(job_id=...)to clean up the scratch runAlso noted that this workflow's plan comes back
basis: "unknown"withminutes: null, so the recipe now says to quote seconds (a few, in practice), not minutes — and dropped the old "two calls" undercount.Changed:
dw_mcp/server.py—get_output_audiodocstringplugins/dw/skills/minimax-h3/SKILL.md— "Run and judge" step 4 (trimmed elsewhere in the same step to stay under the skill's 12288-byte cap after the addition)plugins/dw/skills/series-episodes/SKILL.md— "Run and judge" sectionShipped: commit
4a09cadondevelop, deployed tolemat 2026-09-23 17:25 UTC (healthy, mcp=true).ruffclean;tests/test_mcp_server.pyandtests/test_plugin_skills.py(171 tests total) both pass, including the skill byte-size cap.Doc-only again, no engine or MCP interface change — not a breaking change.
dkackman commentedon Sep 23, 2026
Verified as claude-opus-5-5 (Anthropic) against develop @ 0963746 (includes 4a09cad).
I followed the documented recipe exactly as the
get_output_audiodocstring now gives it: validate, then run withacknowledged_costbound to the plan, thenget_output_text, thendelete_output(job_id=...). I did it for both cases Don named:output:templates/generate-speech/20260919-001130-ab0839ac/GenerateSpeech-speak.0-0.0.wavvalidate_workflow(name="templates/transcribe-audio", arguments={"input_audio": ...})came back valid. The plan hadbasis: "unknown",minutes: nullanddownloads_required: [].run_workflow(..., acknowledged_cost={"fingerprint": "sha256:44d9e7…", "minutes": null, "downloads": []}, wait_seconds=55)went through with no refusal. Job33db845db321succeeded in 4 s.get_output_textreturned "somebody finished the pistachio and nobody is saying anything."delete_output(job_id="33db845db321")returneddeleted: true.output:templates/minimax/video-with-audio/20260914-130839-153a8e27/MiniMaxH3-text_to_video_audio.0-0.0.mp4unknown/null plan. The run with a bound ack was job9dc7550f36c9, which succeeded in 2 s.delete_output(job_id=...)returneddeleted: true.Both runs took seconds, which matches the docstring's "quote seconds, not minutes". The "two calls" wording is gone and the docstring now says "Four calls and a short wait".
Skills, as loaded from develop:
dw:series-episodes"Run and judge" has the full route: validate, a boundacknowledged_cost,get_output_text,delete_output(job_id=...), and the seconds-not-minutes quote.dw:minimax-h3"Run and judge" names the same four steps, points at the docstring for the details, and gives the same quoting note.