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
resample_audio advertises a parameter its implementation does not accept #185
tool/endpoint:get_task("resample_audio") / resample_audio task step repro: pass {"task": {"command": "resample_audio", "arguments": {"audio": "...", "target_sample_rate": 32000, "device": "cpu"}}}. docs/TASKS.md states "Any task that runs a model accepts a "device" argument", and the task schema surfaces device; passing it raises TypeError. expected: either the parameter exists on the implementation, or the schema/docs do not advertise it. A documented, schema-listed argument that type-errors at run time is precisely the failure the server's own pre-flight validation ("validation flags task-argument typos") is meant to catch before a job is queued. actual:resample_audio(audio, target_sample_rate, sample_rate=None) — no device; passing it is a TypeError. Cost a job when first hit. Also worth auditing: the blanket docs claim ("any task that runs a model") — resample_audio is not a model task, so it likely should not carry the claim in the first place.
triage: batch with #187 — both land in dw/tasks/task.py + dw/tasks/audio_utils.py + docs/TASKS.md (and dw/task_domains.py), one lem restart instead of two. Confirmed from source: describe_task (dw/introspection.py:395-427) appends a device parameter to every task's schema on the comment "every task accepts it", but only 11 of the 32 _handle_* dispatchers in dw/tasks/task.py consume it via task.device_for(arguments); the rest (_handle_resample_audio at line 164 included) pass **arguments straight through, so a schema-advertised argument is a TypeError at run time. Fix is the schema/dispatch truth, not a new parameter on resample_audio: either consume device uniformly in the dispatcher (strip it for a task that runs no model) or have describe_task append it only for the handlers that call device_for — and correct the blanket claim at docs/TASKS.md:16 either way. task_argument_errors (dw/task_domains.py:169, #141) does not check argument names against the signature, which is why pre-flight passed this; whether to add that is the session's call. Triaged by model opus via provider anthropic.
describe_task() always advertises device on every task's schema since it's a universal, always-safe-to-pass override — but non-model commands were forwarding arguments straight to their implementation, whose signature never took device, so passing it raised TypeError (as reported for resample_audio).
register_command() (dw/tasks/task.py) now takes a consumes_device flag (default False). A non-consuming handler pops device from arguments before dispatch (guarded to only pop when arguments is actually a dict, since a command like gather_inputs receives a plain list). The 8 model-backed handlers that resolve their own device via task.device_for(arguments) are marked consumes_device=True and left unwrapped, so their existing device-selection behavior is unchanged.
docs/TASKS.md already documented device as available on every task (that claim was accurate); no correction needed there.
Commit: 1f3c8f1, merged to develop at 09875d9, deployed to lem (server restarted, get_health → status: ok, get_task("resample_audio") still lists device, and a live dispatch with an explicit device argument succeeds).
Model sonnet via provider anthropic.
Proposed regression case (not added to the suite, for the tester to place): in tests/test_task.py, call any non-model command through _COMMAND_REGISTRY (e.g. resample_audio or the new gain_audio from #187) with an explicit device argument and assert it succeeds rather than raising TypeError. Also worth pinning: gather_inputs (or any command whose arguments is not a dict) still succeeds with the wrapper in place — that's what the guard added during this fix protects against.
Verified against dw 0.4.0-beta.6 on lem (get_health → ok, cuda), over MCP only, in a throwaway workspace qa-verify-185 (deleted afterwards). Tester model opus via provider anthropic.
Exact repro — inline workflow, one step resample_audio with {"audio": "asset:uploads/qa-cast/room-bed.wav", "target_sample_rate": 32000, "device": "cpu"}:
validate_workflow → valid (still no complaint about device, correct now that it's consumed).
run_workflow → job 242d79ae47d0succeeded in 2.9 s, manifest final/resampled-0.0.wav. No TypeError.
resample_audio again with device: "cuda:0" (a non-cpu spelling) → ran, wrote final/resampled2-0.0.wav.
gather_inputs with a dict that includes device → step was elided by the engine (nothing consumed it), so that's not evidence either way for the non-dict guard; the list-shaped gather_inputs path is reachable only through previous_result fan-out and isn't constructible from a plain inline workflow, so that part of the proposed case belongs in the dw pytest suite as the implementer suggested, not here.
get_task("resample_audio") and get_task("gain_audio") both still advertise device with the "device override for this task" description — schema and runtime now agree, which is what expected: asked for.
Adding a smoke regression case for the MCP-reachable half (non-model task accepts an explicit device).
Activity
dkackman commentedon Sep 17, 2026
triage: batch with #187 — both land in
dw/tasks/task.py+dw/tasks/audio_utils.py+docs/TASKS.md(anddw/task_domains.py), one lem restart instead of two. Confirmed from source:describe_task(dw/introspection.py:395-427) appends adeviceparameter to every task's schema on the comment "every task accepts it", but only 11 of the 32_handle_*dispatchers indw/tasks/task.pyconsume it viatask.device_for(arguments); the rest (_handle_resample_audioat line 164 included) pass**argumentsstraight through, so a schema-advertised argument is aTypeErrorat run time. Fix is the schema/dispatch truth, not a new parameter onresample_audio: either consumedeviceuniformly in the dispatcher (strip it for a task that runs no model) or havedescribe_taskappend it only for the handlers that calldevice_for— and correct the blanket claim atdocs/TASKS.md:16either way.task_argument_errors(dw/task_domains.py:169, #141) does not check argument names against the signature, which is why pre-flight passed this; whether to add that is the session's call. Triaged by model opus via provider anthropic.fix(tasks): #185 #187 - stop advertising device on non-consuming task…
Merge fix/185-187-task-device-and-gain-audio
dkackman commentedon Sep 17, 2026
Fixed and deployed.
describe_task()always advertisesdeviceon every task's schema since it's a universal, always-safe-to-pass override — but non-model commands were forwardingargumentsstraight to their implementation, whose signature never tookdevice, so passing it raisedTypeError(as reported forresample_audio).register_command()(dw/tasks/task.py) now takes aconsumes_deviceflag (defaultFalse). A non-consuming handler popsdevicefromargumentsbefore dispatch (guarded to only pop whenargumentsis actually a dict, since a command likegather_inputsreceives a plain list). The 8 model-backed handlers that resolve their own device viatask.device_for(arguments)are markedconsumes_device=Trueand left unwrapped, so their existing device-selection behavior is unchanged.docs/TASKS.mdalready documenteddeviceas available on every task (that claim was accurate); no correction needed there.Commit: 1f3c8f1, merged to
developat 09875d9, deployed tolem(server restarted,get_health→status: ok,get_task("resample_audio")still listsdevice, and a live dispatch with an explicitdeviceargument succeeds).Model sonnet via provider anthropic.
Proposed regression case (not added to the suite, for the tester to place): in
tests/test_task.py, call any non-model command through_COMMAND_REGISTRY(e.g.resample_audioor the newgain_audiofrom #187) with an explicitdeviceargument and assert it succeeds rather than raisingTypeError. Also worth pinning:gather_inputs(or any command whoseargumentsis not a dict) still succeeds with the wrapper in place — that's what the guard added during this fix protects against.dkackman commentedon Sep 17, 2026
Verified against dw 0.4.0-beta.6 on
lem(get_health→ ok, cuda), over MCP only, in a throwaway workspaceqa-verify-185(deleted afterwards). Tester model opus via provider anthropic.Exact repro — inline workflow, one step
resample_audiowith{"audio": "asset:uploads/qa-cast/room-bed.wav", "target_sample_rate": 32000, "device": "cpu"}:validate_workflow→ valid (still no complaint aboutdevice, correct now that it's consumed).run_workflow→ job242d79ae47d0succeeded in 2.9 s, manifestfinal/resampled-0.0.wav. NoTypeError.Adjacent cases (job
1b501f78d203, succeeded):gain_audio(new in No per-region gain task; ducking requires a five-step slice/gain/rejoin chain #187, non-model) withdevice: "cuda"plusgain_db: -6, start_seconds: 0, duration_seconds: 1→ ran, wrotefinal/gained-0.0.wav.resample_audioagain withdevice: "cuda:0"(a non-cpuspelling) → ran, wrotefinal/resampled2-0.0.wav.gather_inputswith a dict that includesdevice→ step was elided by the engine (nothing consumed it), so that's not evidence either way for the non-dict guard; the list-shapedgather_inputspath is reachable only throughprevious_resultfan-out and isn't constructible from a plain inline workflow, so that part of the proposed case belongs in the dw pytest suite as the implementer suggested, not here.get_task("resample_audio")andget_task("gain_audio")both still advertisedevicewith the "device override for this task" description — schema and runtime now agree, which is whatexpected:asked for.Adding a smoke regression case for the MCP-reachable half (non-model task accepts an explicit
device).Develop (#241)