diffusers-workflow 0.16.0__tar.gz → 0.17.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (691) hide show
  1. {diffusers_workflow-0.16.0/diffusers_workflow.egg-info → diffusers_workflow-0.17.0}/PKG-INFO +5 -6
  2. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/README.md +2 -1
  3. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0/diffusers_workflow.egg-info}/PKG-INFO +5 -6
  4. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/diffusers_workflow.egg-info/SOURCES.txt +47 -20
  5. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/diffusers_workflow.egg-info/requires.txt +1 -1
  6. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/__init__.py +3 -3
  7. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/arguments.py +4 -1
  8. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/content_types.py +23 -11
  9. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/ARCHITECTURE.md +10 -7
  10. diffusers_workflow-0.17.0/dw/docs/ATTRIBUTIONS.md +111 -0
  11. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/DEPENDENCIES.md +1 -1
  12. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/MCP.md +12 -5
  13. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/RELEASING.md +130 -0
  14. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/SECURITY.md +39 -2
  15. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/SERVER.md +9 -6
  16. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/TASKS.md +229 -26
  17. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/WORKFLOW_GUIDE.md +146 -21
  18. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/dsp.py +45 -0
  19. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/for_each.py +21 -0
  20. diffusers_workflow-0.17.0/dw/hold_audio.py +358 -0
  21. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/locations.py +5 -3
  22. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/media.py +26 -349
  23. diffusers_workflow-0.17.0/dw/media_readers.py +410 -0
  24. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/chain.py +2 -2
  25. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/components.py +3 -0
  26. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/h3_hold.py +23 -9
  27. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/h3_hold_steps.py +51 -10
  28. diffusers_workflow-0.17.0/dw/pipeline_processors/h3_mask.py +111 -0
  29. diffusers_workflow-0.17.0/dw/pipeline_processors/h3_mask_cells.py +92 -0
  30. diffusers_workflow-0.17.0/dw/pipeline_processors/h3_mask_steps.py +243 -0
  31. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/h3_rules.py +262 -13
  32. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/pipeline.py +105 -140
  33. diffusers_workflow-0.17.0/dw/pipeline_processors/pipeline_outputs.py +144 -0
  34. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/timing.py +44 -9
  35. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/plan_downloads.py +41 -8
  36. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/previous_results.py +52 -1
  37. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/runs.py +4 -2
  38. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/script_lines.py +2 -2
  39. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/catalog_shape.py +11 -1
  40. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/http_security.py +3 -10
  41. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/routes/jobs.py +3 -0
  42. diffusers_workflow-0.16.0/dw/server/ui/assets/cssMode-Cx99RWkL.js → diffusers_workflow-0.17.0/dw/server/ui/assets/cssMode-BvFOC5nO.js +1 -1
  43. diffusers_workflow-0.16.0/dw/server/ui/assets/editor.api-jKhYFhrF.js → diffusers_workflow-0.17.0/dw/server/ui/assets/editor.api-ChcCMXXR.js +1 -1
  44. diffusers_workflow-0.16.0/dw/server/ui/assets/freemarker2-Cr_kdwwJ.js → diffusers_workflow-0.17.0/dw/server/ui/assets/freemarker2-DT2q5NS2.js +1 -1
  45. diffusers_workflow-0.16.0/dw/server/ui/assets/handlebars-CnbOycVf.js → diffusers_workflow-0.17.0/dw/server/ui/assets/handlebars-kaJu_3a1.js +1 -1
  46. diffusers_workflow-0.16.0/dw/server/ui/assets/html-vCIOVoPc.js → diffusers_workflow-0.17.0/dw/server/ui/assets/html-BsNsYnSX.js +1 -1
  47. diffusers_workflow-0.16.0/dw/server/ui/assets/htmlMode-B5ESZlHK.js → diffusers_workflow-0.17.0/dw/server/ui/assets/htmlMode-BcQxv5VO.js +1 -1
  48. diffusers_workflow-0.16.0/dw/server/ui/assets/index-DIXj1Pp3.js → diffusers_workflow-0.17.0/dw/server/ui/assets/index-CN0qvKxj.js +45 -45
  49. diffusers_workflow-0.16.0/dw/server/ui/assets/javascript-DpV2UaWD.js → diffusers_workflow-0.17.0/dw/server/ui/assets/javascript-CEdXynRF.js +1 -1
  50. diffusers_workflow-0.16.0/dw/server/ui/assets/jsonMode-DaGlZZy1.js → diffusers_workflow-0.17.0/dw/server/ui/assets/jsonMode-hbOYEMCP.js +1 -1
  51. diffusers_workflow-0.16.0/dw/server/ui/assets/liquid-Ds835QKV.js → diffusers_workflow-0.17.0/dw/server/ui/assets/liquid-JLSoiOSA.js +1 -1
  52. diffusers_workflow-0.16.0/dw/server/ui/assets/lspLanguageFeatures-Cd9OxrIO.js → diffusers_workflow-0.17.0/dw/server/ui/assets/lspLanguageFeatures-BOyNtxH5.js +1 -1
  53. diffusers_workflow-0.16.0/dw/server/ui/assets/mdx-BozOHFIi.js → diffusers_workflow-0.17.0/dw/server/ui/assets/mdx-sDDXTu9v.js +1 -1
  54. diffusers_workflow-0.16.0/dw/server/ui/assets/monaco-673w9Wwq.js → diffusers_workflow-0.17.0/dw/server/ui/assets/monaco-1MuWdUz9.js +4 -4
  55. diffusers_workflow-0.16.0/dw/server/ui/assets/python-D_HjE-WC.js → diffusers_workflow-0.17.0/dw/server/ui/assets/python-FwMP_5s9.js +1 -1
  56. diffusers_workflow-0.16.0/dw/server/ui/assets/razor-DjEZAQZw.js → diffusers_workflow-0.17.0/dw/server/ui/assets/razor-CHr8DUwq.js +1 -1
  57. diffusers_workflow-0.16.0/dw/server/ui/assets/tsMode-B3g7-HAd.js → diffusers_workflow-0.17.0/dw/server/ui/assets/tsMode-DMRBdzCs.js +1 -1
  58. diffusers_workflow-0.16.0/dw/server/ui/assets/typescript-Bq3yLFs6.js → diffusers_workflow-0.17.0/dw/server/ui/assets/typescript-DX26K2Zt.js +1 -1
  59. diffusers_workflow-0.16.0/dw/server/ui/assets/workers-Jt2I7Jya.js → diffusers_workflow-0.17.0/dw/server/ui/assets/workers-C00WfVNJ.js +1 -1
  60. diffusers_workflow-0.16.0/dw/server/ui/assets/xml-BD0Sm95a.js → diffusers_workflow-0.17.0/dw/server/ui/assets/xml-5-4XmnnO.js +1 -1
  61. diffusers_workflow-0.16.0/dw/server/ui/assets/yaml-BSnko3ic.js → diffusers_workflow-0.17.0/dw/server/ui/assets/yaml-DjHDC-oK.js +1 -1
  62. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/index.html +1 -1
  63. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/updater.py +1 -1
  64. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/step_value_checks.py +3 -11
  65. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/task_domains.py +42 -5
  66. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/task_problems.py +58 -6
  67. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/audio_transcription.py +88 -7
  68. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/cuts.py +137 -297
  69. diffusers_workflow-0.17.0/dw/tasks/cuts_lines.py +380 -0
  70. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/face_track.py +228 -48
  71. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/fit.py +46 -8
  72. diffusers_workflow-0.17.0/dw/tasks/mmaudio_decoder.py +128 -0
  73. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/model_handlers.py +53 -0
  74. diffusers_workflow-0.17.0/dw/tasks/phrases.py +285 -0
  75. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/script_check.py +143 -489
  76. diffusers_workflow-0.17.0/dw/tasks/script_findings.py +580 -0
  77. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/script_take.py +77 -2
  78. diffusers_workflow-0.17.0/dw/tasks/sound_effects.py +519 -0
  79. diffusers_workflow-0.17.0/dw/tasks/speech_generation.py +551 -0
  80. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/task.py +6 -0
  81. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/video_handlers.py +50 -7
  82. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/voice_attribution.py +34 -9
  83. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/windows.py +11 -4
  84. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/trust.py +97 -0
  85. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/validation.py +30 -3
  86. diffusers_workflow-0.17.0/dw/vendored/__init__.py +11 -0
  87. diffusers_workflow-0.17.0/dw/vendored/audio8_tts_model.py +2033 -0
  88. diffusers_workflow-0.17.0/dw/vendored/mmaudio_clip.py +399 -0
  89. diffusers_workflow-0.17.0/dw/vendored/mmaudio_model.py +772 -0
  90. diffusers_workflow-0.17.0/dw/vendored/mmaudio_sync_model.py +452 -0
  91. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/video_extensions.py +6 -1
  92. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/workflow_schema.json +1 -1
  93. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/writers.py +71 -0
  94. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/pyproject.toml +4 -6
  95. diffusers_workflow-0.17.0/tests/test_analyze_phrases.py +231 -0
  96. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_arch_metrics.py +11 -0
  97. diffusers_workflow-0.17.0/tests/test_audio8_tts_model.py +362 -0
  98. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_catalog_shape.py +33 -0
  99. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_catalog_structure.py +49 -3
  100. diffusers_workflow-0.17.0/tests/test_cost_scaling_h3_frames.py +23 -0
  101. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_dsp.py +26 -0
  102. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_face_track.py +277 -1
  103. diffusers_workflow-0.17.0/tests/test_fit_templates.py +400 -0
  104. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_fit_to_model.py +118 -0
  105. diffusers_workflow-0.17.0/tests/test_fractional_fps.py +94 -0
  106. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_hold_audio.py +56 -1
  107. diffusers_workflow-0.17.0/tests/test_h3_mask.py +1164 -0
  108. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_refine.py +271 -0
  109. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_rules.py +1 -1
  110. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_sparse_defaults.py +3 -2
  111. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_jobs_listing.py +15 -0
  112. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_join_windows.py +26 -0
  113. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_locations.py +65 -0
  114. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_ltx2_ic_loras.py +195 -4
  115. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_ltx_prompt_library.py +5 -0
  116. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_server.py +3 -2
  117. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_media_frames.py +1 -1
  118. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_media_layering.py +2 -2
  119. diffusers_workflow-0.17.0/tests/test_media_sample_frames.py +144 -0
  120. diffusers_workflow-0.17.0/tests/test_mmaudio_decoder.py +162 -0
  121. diffusers_workflow-0.17.0/tests/test_mmaudio_model.py +545 -0
  122. diffusers_workflow-0.17.0/tests/test_mmaudio_sync_model.py +195 -0
  123. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_plan.py +70 -1
  124. diffusers_workflow-0.17.0/tests/test_plan_cuts_phrases.py +248 -0
  125. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_plugin_skills.py +222 -2
  126. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_previous_results.py +163 -0
  127. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_result_fps.py +4 -9
  128. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_runs.py +21 -0
  129. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_script_check.py +212 -3
  130. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_security_trust_gate.py +180 -0
  131. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_security_web_headers.py +21 -7
  132. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_separate_stems.py +20 -3
  133. diffusers_workflow-0.17.0/tests/test_sound_effects.py +420 -0
  134. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_speech_generation.py +306 -0
  135. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_step_cache.py +15 -0
  136. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_step_timing.py +51 -0
  137. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_task_discovery.py +34 -0
  138. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_task_domains.py +18 -0
  139. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_task_registry_rules.py +1 -0
  140. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_task_weights.py +122 -0
  141. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_transcribe_audio.py +144 -0
  142. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_validation.py +3 -0
  143. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_video_extensions.py +40 -7
  144. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_voice_attribution.py +24 -0
  145. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_workflow_trust.py +25 -0
  146. diffusers_workflow-0.16.0/dw/hold_audio.py +0 -162
  147. diffusers_workflow-0.16.0/dw/tasks/speech_generation.py +0 -281
  148. diffusers_workflow-0.16.0/tests/test_fit_templates.py +0 -137
  149. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/LICENSE +0 -0
  150. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/MANIFEST.in +0 -0
  151. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/diffusers_workflow.egg-info/dependency_links.txt +0 -0
  152. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/diffusers_workflow.egg-info/entry_points.txt +0 -0
  153. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/diffusers_workflow.egg-info/top_level.txt +0 -0
  154. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/acceleration_warnings.py +0 -0
  155. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/adapter_compatibility.py +0 -0
  156. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/argument_media.py +0 -0
  157. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/argument_warnings.py +0 -0
  158. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/assessment_rules.py +0 -0
  159. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/assets.py +0 -0
  160. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/audio_qc.py +0 -0
  161. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/cache_blocks.json +0 -0
  162. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/cache_blocks.py +0 -0
  163. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/community_pipelines/pipeline_flux_rf_inversion.py +0 -0
  164. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/community_pipelines/pipeline_ltx2_refine.py +0 -0
  165. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/cost_scaling.py +0 -0
  166. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/devices.py +0 -0
  167. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/disk_caches.py +0 -0
  168. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/dissolve_frame_errors.py +0 -0
  169. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/ACCELERATION.md +0 -0
  170. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/AGENT_LOOP.md +0 -0
  171. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/IP_ADAPTER.md +0 -0
  172. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/LORAS.md +0 -0
  173. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/PROMPT_WEIGHTING.md +0 -0
  174. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/QUANTIZATION.md +0 -0
  175. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/RECIPES_24GB.md +0 -0
  176. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/REMOTE.md +0 -0
  177. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/SECURITY_QUICKREF.md +0 -0
  178. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/TESTING.md +0 -0
  179. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/WORKER_GUIDE.md +0 -0
  180. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/docs/WORKSPACES.md +0 -0
  181. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/download_watch.py +0 -0
  182. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/elision.py +0 -0
  183. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/events.py +0 -0
  184. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/guides.py +0 -0
  185. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/host_memory.py +0 -0
  186. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/host_memory_projection.py +0 -0
  187. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/hub_cache.py +0 -0
  188. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/introspection.py +0 -0
  189. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/kernel_availability.py +0 -0
  190. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/library.py +0 -0
  191. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/log_setup.py +0 -0
  192. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/lora_catalog.py +0 -0
  193. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/lora_catalog_schema.json +0 -0
  194. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/lora_hub.py +0 -0
  195. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/media_compare.py +0 -0
  196. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/media_frames.py +0 -0
  197. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/media_types.py +0 -0
  198. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/notes.py +0 -0
  199. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/outbound.py +0 -0
  200. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/output_extraction.py +0 -0
  201. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/path_redaction.py +0 -0
  202. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_ownership.py +0 -0
  203. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/adapters.py +0 -0
  204. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/config_objects.py +0 -0
  205. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/h3_guide_steps.py +0 -0
  206. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/h3_guides.py +0 -0
  207. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/h3_tiles.py +0 -0
  208. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/mag_calibration.py +0 -0
  209. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/placement.py +0 -0
  210. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/progress.py +0 -0
  211. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/pipeline_processors/remote.py +0 -0
  212. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/plan.py +0 -0
  213. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/probe_paths.py +0 -0
  214. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/prompt_schema.json +0 -0
  215. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/prompt_weighting.py +0 -0
  216. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/prompts.py +0 -0
  217. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/quantized_cache.py +0 -0
  218. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/realize.py +0 -0
  219. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/reference_limits.py +0 -0
  220. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/reference_names.py +0 -0
  221. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/references.py +0 -0
  222. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/result.py +1 -1
  223. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/roles.py +0 -0
  224. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/run.py +0 -0
  225. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/scalar_result_validation.py +0 -0
  226. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/schema.py +0 -0
  227. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/security.py +0 -0
  228. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/serve.py +0 -0
  229. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/__init__.py +0 -0
  230. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/admission.py +0 -0
  231. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/api_models.py +0 -0
  232. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/api_models_base.py +0 -0
  233. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/api_models_library.py +0 -0
  234. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/app.py +0 -0
  235. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/assess.py +0 -0
  236. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/catalog.py +0 -0
  237. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/deps.py +0 -0
  238. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/dispatch.py +0 -0
  239. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/enhancers.py +0 -0
  240. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/exports.py +0 -0
  241. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/guides.py +0 -0
  242. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/host_ram_need.py +0 -0
  243. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/inline_media.py +0 -0
  244. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/job_history.py +0 -0
  245. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/job_record.py +0 -0
  246. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/job_results.py +0 -0
  247. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/jobs.py +0 -0
  248. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/mcp_mount.py +0 -0
  249. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/netinfo.py +0 -0
  250. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/observed_cost.py +0 -0
  251. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/outputs.py +0 -0
  252. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/pool.py +0 -0
  253. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/routes/__init__.py +0 -0
  254. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/routes/assets.py +0 -0
  255. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/routes/files.py +0 -0
  256. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/routes/gallery.py +0 -0
  257. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/routes/library.py +0 -0
  258. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/routes/loras.py +0 -0
  259. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/routes/media.py +0 -0
  260. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/routes/system.py +0 -0
  261. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/sysinfo.py +0 -0
  262. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/abap-08VXUWAP.js +0 -0
  263. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/apex-BWPQTe0t.js +0 -0
  264. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/azcli-Bc_sGQ0U.js +0 -0
  265. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/bat-i0X4ZdIN.js +0 -0
  266. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/bicep-B5-_aFwp.js +0 -0
  267. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/cameligo-DMUM7wLl.js +0 -0
  268. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/clojure-Cm7r79vr.js +0 -0
  269. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/codicon-DF1abBS2.ttf +0 -0
  270. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/coffee-Ba7i2nA0.js +0 -0
  271. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/cpp-C7h46wYY.js +0 -0
  272. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/csharp-BKxtCVv1.js +0 -0
  273. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/csp-bTuwJoIa.js +0 -0
  274. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/css-DIMkf-bt.js +0 -0
  275. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/css.worker-C6lDtRpF.js +0 -0
  276. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/cypher-CVaqCwHa.js +0 -0
  277. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/dart-onAF5SnQ.js +0 -0
  278. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/dockerfile-DZFCIeNp.js +0 -0
  279. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/ecl-D05T4iGw.js +0 -0
  280. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/editor-DjpsE8to.css +0 -0
  281. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/editor.worker-BmdWdrHZ.js +0 -0
  282. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/elixir-6RTg0lbw.js +0 -0
  283. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/flow9-C5_-GSwl.js +0 -0
  284. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/fsharp-C8Ef5oNN.js +0 -0
  285. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/go-C-y9NEjX.js +0 -0
  286. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/graphql-fmXr3nnJ.js +0 -0
  287. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/hcl-CpzslTdj.js +0 -0
  288. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/html.worker-C5yZDBHz.js +0 -0
  289. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/index-Bm_jBlG4.css +0 -0
  290. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/ini-sBoK_t0W.js +0 -0
  291. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/java-BEtHBSE6.js +0 -0
  292. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/json.worker-DdeUAmHa.js +0 -0
  293. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/julia-Bri6UV-V.js +0 -0
  294. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/kotlin-BOotOW0E.js +0 -0
  295. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/less-B9JPFI3C.js +0 -0
  296. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/lexon-CfSJPG6W.js +0 -0
  297. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/lua-CsQS60Ue.js +0 -0
  298. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/m3-D-oSqn_W.js +0 -0
  299. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/markdown-Cimd5fb3.js +0 -0
  300. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/mips-CIPQ_RoX.js +0 -0
  301. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/monaco-n7clI0si.css +0 -0
  302. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/msdax-DauUninz.js +0 -0
  303. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/mysql-SOo6toE5.js +0 -0
  304. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/objective-c-FvmIjYaQ.js +0 -0
  305. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/pascal-DrH0SRf2.js +0 -0
  306. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/pascaligo-D-ptJ9y-.js +0 -0
  307. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/perl-oz_6vUea.js +0 -0
  308. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/pgsql-DTj74zXo.js +0 -0
  309. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/php-nr791fC2.js +0 -0
  310. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/pla-CopQ2nXW.js +0 -0
  311. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/postiats-43DmfD33.js +0 -0
  312. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/powerquery-D3hlyOfw.js +0 -0
  313. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/powershell-DmHpPYUd.js +0 -0
  314. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/protobuf-C531GsRP.js +0 -0
  315. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/pug-Z5eAx3Zn.js +0 -0
  316. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/qsharp-DkqhCAOL.js +0 -0
  317. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/r-BwWrilGY.js +0 -0
  318. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/redis-ClamHrr6.js +0 -0
  319. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/redshift-DT7zqm-g.js +0 -0
  320. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/restructuredtext-BYgofb2h.js +0 -0
  321. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/ruby-DezsRK8O.js +0 -0
  322. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/rust-DdL9SqIa.js +0 -0
  323. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/sb-CcwsVR0C.js +0 -0
  324. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/scala-DHpiXF5c.js +0 -0
  325. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/scheme-BeGwcela.js +0 -0
  326. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/scss-gp-XZpBa.js +0 -0
  327. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/shell-CC2rA5mh.js +0 -0
  328. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/solidity-BEEn4gHE.js +0 -0
  329. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/sophia-CRfGWb83.js +0 -0
  330. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/sparql-D_Lu-MrJ.js +0 -0
  331. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/sql-NEE52Syq.js +0 -0
  332. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/st-DbInun42.js +0 -0
  333. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/swift-Bxkupp3x.js +0 -0
  334. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/systemverilog-Bz4Y3fRF.js +0 -0
  335. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/tcl-DISqw1ZD.js +0 -0
  336. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/ts.worker-DGGa2mF8.js +0 -0
  337. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/twig-De2hgUGE.js +0 -0
  338. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/typespec-B8J7ngcE.js +0 -0
  339. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/vb-DV3o63ZY.js +0 -0
  340. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/ui/assets/wgsl-DpFanUEy.js +0 -0
  341. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/server/worker_memory.py +0 -0
  342. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/settings.py +0 -0
  343. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/shot_span_preflight.py +0 -0
  344. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/shots.py +0 -0
  345. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/slice_preflight.py +0 -0
  346. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/sparse_attention.py +0 -0
  347. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/step.py +0 -0
  348. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/step_cache.py +0 -0
  349. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/subfolders.py +0 -0
  350. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/assess.py +0 -0
  351. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/audio_dynamics.py +0 -0
  352. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/audio_handlers.py +0 -0
  353. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/audio_utils.py +0 -0
  354. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/background_remover.py +0 -0
  355. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/beats.py +0 -0
  356. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/borders.py +0 -0
  357. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/compose_text.py +0 -0
  358. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/concat_videos.py +0 -0
  359. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/depth_estimator.py +0 -0
  360. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/diffusion_upscale.py +0 -0
  361. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/dissolve_videos.py +0 -0
  362. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/finish.py +0 -0
  363. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/finish_handlers.py +0 -0
  364. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/format_messages.py +0 -0
  365. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/gather.py +0 -0
  366. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/grade.py +0 -0
  367. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/h3_latent_upscale.py +0 -0
  368. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/h3_latent_upscaler_model.py +0 -0
  369. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/image_ops.py +0 -0
  370. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/image_to_text.py +0 -0
  371. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/image_utils.py +0 -0
  372. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/interpolate_frames.py +0 -0
  373. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/join_into_song.py +0 -0
  374. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/joins.py +0 -0
  375. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/judge.py +0 -0
  376. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/loop_bed.py +0 -0
  377. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/lut.py +0 -0
  378. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/measure_sync.py +0 -0
  379. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/model_cache.py +0 -0
  380. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/pair_audio.py +0 -0
  381. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/qr_code.py +0 -0
  382. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/registry.py +0 -0
  383. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/remove_object.py +0 -0
  384. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/restore_faces.py +0 -0
  385. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/rife_model.py +0 -0
  386. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/segment.py +0 -0
  387. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/select.py +0 -0
  388. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/stabilize.py +0 -0
  389. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/tensor_image.py +0 -0
  390. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/text_generation.py +0 -0
  391. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/text_sections.py +0 -0
  392. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/trim.py +0 -0
  393. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/upscale.py +0 -0
  394. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/video_utils.py +0 -0
  395. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/weights.py +0 -0
  396. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/tasks/zoe_depth.py +0 -0
  397. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/test.py +0 -0
  398. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/type_helpers.py +0 -0
  399. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/type_references.py +0 -0
  400. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/validate.py +0 -0
  401. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/variable_constraints.py +0 -0
  402. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/variables.py +0 -0
  403. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/video_size_errors.py +0 -0
  404. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/vram_estimate.py +0 -0
  405. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/vram_inheritance.py +0 -0
  406. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/window_count_errors.py +0 -0
  407. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/worker.py +0 -0
  408. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/worker_manager.py +0 -0
  409. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/worker_protocol.py +0 -0
  410. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/workflow.py +0 -0
  411. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/workflow_run.py +0 -0
  412. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/workflows/flux3_klein_upsample.json +0 -0
  413. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/workflows/flux3_klein_upsample_edit.json +0 -0
  414. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/workflows/h3_context_ir.json +0 -0
  415. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/workflows/test.json +0 -0
  416. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/workspace.py +0 -0
  417. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw/workspace_copy.py +0 -0
  418. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/__init__.py +0 -0
  419. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/__main__.py +0 -0
  420. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/assets.py +0 -0
  421. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/authoring.py +0 -0
  422. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/catalog.py +0 -0
  423. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/client.py +0 -0
  424. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/confine.py +0 -0
  425. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/diagnose.py +0 -0
  426. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/exports.py +0 -0
  427. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/guides.py +0 -0
  428. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/loras.py +0 -0
  429. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/media.py +0 -0
  430. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/models.py +0 -0
  431. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/prompts.py +0 -0
  432. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/server.py +0 -0
  433. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/tools_authoring.py +0 -0
  434. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/tools_catalog.py +0 -0
  435. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/tools_jobs.py +0 -0
  436. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/tools_media.py +0 -0
  437. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/dw_mcp/workspaces.py +0 -0
  438. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/setup.cfg +0 -0
  439. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_admission.py +0 -0
  440. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_admission_capacity.py +0 -0
  441. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_analyze_beats.py +0 -0
  442. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_api_contract.py +0 -0
  443. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_arch_report.py +0 -0
  444. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_architecture_map.py +0 -0
  445. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_argument_updates.py +0 -0
  446. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_arguments.py +0 -0
  447. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_assemble_and_score_target_lufs.py +0 -0
  448. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_assess.py +0 -0
  449. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_assessment_rules.py +0 -0
  450. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_assets.py +0 -0
  451. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_attention_backend_trace.py +0 -0
  452. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_attention_slicing.py +0 -0
  453. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_audio_utils.py +0 -0
  454. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_best_of_n_template.py +0 -0
  455. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_borders.py +0 -0
  456. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_cache_blocks.py +0 -0
  457. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_cache_stats.py +0 -0
  458. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_catalog_speed_defaults.py +0 -0
  459. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_chain.py +0 -0
  460. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_chain_h3_native.py +0 -0
  461. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_ci_config.py +0 -0
  462. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_cli.py +0 -0
  463. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_compare_route.py +0 -0
  464. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_component_name_errors.py +0 -0
  465. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_component_pruning.py +0 -0
  466. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_component_type_errors.py +0 -0
  467. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_compose_text.py +0 -0
  468. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_concat_videos.py +0 -0
  469. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_config_objects.py +0 -0
  470. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_configuration_schema.py +0 -0
  471. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_content_types.py +0 -0
  472. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_dependencies_declared.py +0 -0
  473. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_depth_estimator.py +0 -0
  474. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_device.py +0 -0
  475. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_device_helpers.py +0 -0
  476. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_device_portability.py +0 -0
  477. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_dialogue_short_voices.py +0 -0
  478. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_diffusion_upscale.py +0 -0
  479. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_disk_caches.py +0 -0
  480. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_dissolve_frame_errors.py +0 -0
  481. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_dissolve_videos.py +0 -0
  482. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_docs_links.py +0 -0
  483. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_download_watch.py +0 -0
  484. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_elision.py +0 -0
  485. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_events.py +0 -0
  486. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_examples.py +0 -0
  487. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_faststart.py +0 -0
  488. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_find_loop_bed.py +0 -0
  489. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_finish.py +0 -0
  490. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_flux3_catalog.py +0 -0
  491. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_for_each.py +0 -0
  492. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_forget_workspace_history.py +0 -0
  493. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_gallery_roles.py +0 -0
  494. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_gather.py +0 -0
  495. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_grade.py +0 -0
  496. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_guide_chain_validation.py +0 -0
  497. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_guide_pointers.py +0 -0
  498. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_guides_validation.py +0 -0
  499. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_adapters.py +0 -0
  500. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_context_ir.py +0 -0
  501. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_guides.py +0 -0
  502. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_latent_upscale.py +0 -0
  503. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_schedule.py +0 -0
  504. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_tiles.py +0 -0
  505. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_upscaler_source.py +0 -0
  506. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_h3_vram_ceiling.py +0 -0
  507. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_hf_placement.py +0 -0
  508. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_host_memory.py +0 -0
  509. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_host_memory_projection.py +0 -0
  510. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_host_ram_need.py +0 -0
  511. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_hub_cache.py +0 -0
  512. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_image_ops.py +0 -0
  513. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_image_to_text.py +0 -0
  514. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_image_utils.py +0 -0
  515. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_inductor_cache_default.py +0 -0
  516. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_ingredients_grid.py +0 -0
  517. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_inherited_cost.py +0 -0
  518. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_integration.py +0 -0
  519. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_interpolate_frames.py +0 -0
  520. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_introspection.py +0 -0
  521. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_job_history_device.py +0 -0
  522. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_job_history_parity.py +0 -0
  523. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_job_history_wal.py +0 -0
  524. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_job_progress.py +0 -0
  525. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_job_warnings.py +0 -0
  526. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_jobs_reused.py +0 -0
  527. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_join_into_song.py +0 -0
  528. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_judge.py +0 -0
  529. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_kernel_availability.py +0 -0
  530. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_library_path.py +0 -0
  531. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_library_sources.py +0 -0
  532. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_list_images.py +0 -0
  533. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_lora_alpha.py +0 -0
  534. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_lora_catalog.py +0 -0
  535. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_lora_disable.py +0 -0
  536. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_lora_hub.py +0 -0
  537. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_lora_library.py +0 -0
  538. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_ltx2_diffusion_decode.py +0 -0
  539. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_ltx2_extend_clip.py +0 -0
  540. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_ltx2_refine_pipeline.py +0 -0
  541. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_lut.py +0 -0
  542. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_assets.py +0 -0
  543. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_authoring.py +0 -0
  544. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_catalog.py +0 -0
  545. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_client.py +0 -0
  546. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_confine.py +0 -0
  547. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_diagnose.py +0 -0
  548. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_exports.py +0 -0
  549. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_guides.py +0 -0
  550. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_loras.py +0 -0
  551. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_main.py +0 -0
  552. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_media.py +0 -0
  553. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_models.py +0 -0
  554. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_prompts.py +0 -0
  555. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_twins.py +0 -0
  556. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mcp_workspaces.py +0 -0
  557. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_measure_sync.py +0 -0
  558. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_media_audio.py +0 -0
  559. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_media_compare.py +0 -0
  560. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_media_decode_threads.py +0 -0
  561. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_media_info.py +0 -0
  562. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mix_audio.py +0 -0
  563. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_model_cache.py +0 -0
  564. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_modular_output_properties.py +0 -0
  565. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_modular_pipeline.py +0 -0
  566. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_modular_progress.py +0 -0
  567. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mps_fallback_warning.py +0 -0
  568. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_mps_rope_precision.py +0 -0
  569. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_notes.py +0 -0
  570. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_notes_api.py +0 -0
  571. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_notes_bookkeeping.py +0 -0
  572. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_null_media.py +0 -0
  573. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_numeric_coercion.py +0 -0
  574. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_observed_cost.py +0 -0
  575. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_offload_placement.py +0 -0
  576. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_outbound.py +0 -0
  577. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_output_references.py +0 -0
  578. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_pair_audio.py +0 -0
  579. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_pair_audio_fit.py +0 -0
  580. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_parallel_loading_default.py +0 -0
  581. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_path_redaction.py +0 -0
  582. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_phase_events.py +0 -0
  583. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_pipeline_caching.py +0 -0
  584. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_pipeline_components.py +0 -0
  585. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_plan_cuts.py +0 -0
  586. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_prepare_pipeline.py +0 -0
  587. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_previous_result_walker_parity.py +0 -0
  588. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_prompt_library.py +0 -0
  589. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_prompt_parser.py +0 -0
  590. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_prompt_references.py +0 -0
  591. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_prompt_weighting.py +0 -0
  592. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_prompts.py +0 -0
  593. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_quantized_cache.py +0 -0
  594. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_read_frame_range.py +0 -0
  595. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_real_models.py +0 -0
  596. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_realize.py +0 -0
  597. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_recenter_crop.py +0 -0
  598. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_reference_limits.py +0 -0
  599. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_reference_names.py +0 -0
  600. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_reference_skip_sets.py +0 -0
  601. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_references.py +0 -0
  602. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_remove_object.py +0 -0
  603. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_rerun_lineage.py +0 -0
  604. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_rerun_new_seed.py +0 -0
  605. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_resize_bucket.py +0 -0
  606. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_restore_faces_helper_cache.py +0 -0
  607. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_restore_faces_video.py +0 -0
  608. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_result.py +0 -0
  609. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_result_output_naming.py +0 -0
  610. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_roles.py +0 -0
  611. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_rule_parity.py +0 -0
  612. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_run_manifest_roles.py +0 -0
  613. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_runtime_settings.py +0 -0
  614. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_scalar_result_validation.py +0 -0
  615. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_scheduler_config.py +0 -0
  616. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_schema.py +0 -0
  617. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_seam_look.py +0 -0
  618. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_security.py +0 -0
  619. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_security_auth.py +0 -0
  620. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_security_decoder_bombs.py +0 -0
  621. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_security_input_caps.py +0 -0
  622. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_security_ssrf.py +0 -0
  623. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_security_symlinks.py +0 -0
  624. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_segment.py +0 -0
  625. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_select.py +0 -0
  626. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_select_validation.py +0 -0
  627. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_serve_main.py +0 -0
  628. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server.py +0 -0
  629. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_assess.py +0 -0
  630. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_downloads.py +0 -0
  631. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_exports.py +0 -0
  632. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_gallery_image.py +0 -0
  633. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_guides.py +0 -0
  634. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_info.py +0 -0
  635. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_jobs.py +0 -0
  636. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_library_path.py +0 -0
  637. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_loras.py +0 -0
  638. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_mcp.py +0 -0
  639. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_server_workspaces.py +0 -0
  640. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_shaping_logs.py +0 -0
  641. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_shot_span_preflight.py +0 -0
  642. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_shots.py +0 -0
  643. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_slice_preflight.py +0 -0
  644. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_sparse_attention_backends.py +0 -0
  645. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_sparse_attention_processor.py +0 -0
  646. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_sparse_attention_tiles.py +0 -0
  647. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_sparse_attention_wiring.py +0 -0
  648. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_stabilize.py +0 -0
  649. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_stars.py +0 -0
  650. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_step.py +0 -0
  651. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_strip_exif_and_watermark.py +0 -0
  652. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_sub_workflow_resolver.py +0 -0
  653. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_subfolders.py +0 -0
  654. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_task.py +0 -0
  655. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_task_file_weights.py +0 -0
  656. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_task_public_imports.py +0 -0
  657. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_task_signature_errors.py +0 -0
  658. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_template_defaults.py +0 -0
  659. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_template_subfolders.py +0 -0
  660. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_tensor_image.py +0 -0
  661. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_text_generation.py +0 -0
  662. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_text_sections.py +0 -0
  663. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_trim_video.py +0 -0
  664. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_type_helpers.py +0 -0
  665. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_type_helpers_concurrency.py +0 -0
  666. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_ui_twins.py +0 -0
  667. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_unbraced_type_warning.py +0 -0
  668. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_updater.py +0 -0
  669. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_validate_arguments.py +0 -0
  670. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_variable_constraints.py +0 -0
  671. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_variables.py +0 -0
  672. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_video_size_errors.py +0 -0
  673. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_video_utils.py +0 -0
  674. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_vram_estimate.py +0 -0
  675. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_vram_guides.py +0 -0
  676. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_vram_inheritance.py +0 -0
  677. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_window_count_errors.py +0 -0
  678. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_window_video.py +0 -0
  679. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_worker.py +0 -0
  680. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_worker_execute.py +0 -0
  681. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_worker_job_peak_rss.py +0 -0
  682. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_worker_manager.py +0 -0
  683. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_worker_messages.py +0 -0
  684. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_worker_pool.py +0 -0
  685. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_workflow.py +0 -0
  686. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_workflow_run_keys.py +0 -0
  687. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_workflow_snapshot.py +0 -0
  688. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_workflow_step_cache.py +0 -0
  689. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_workspace.py +0 -0
  690. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_workspace_copy.py +0 -0
  691. {diffusers_workflow-0.16.0 → diffusers_workflow-0.17.0}/tests/test_zimage_vram.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffusers-workflow
3
- Version: 0.16.0
3
+ Version: 0.17.0
4
4
  Summary: Declarative workflow engine and web UI for Hugging Face Diffusers
5
5
  Author: dkackman
6
6
  License: Apache-2.0
@@ -8,17 +8,15 @@ Project-URL: Homepage, https://github.com/dkackman/diffusers-workflow
8
8
  Classifier: Development Status :: 3 - Alpha
9
9
  Classifier: Intended Audience :: Developers
10
10
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
11
  Classifier: Programming Language :: Python :: 3.12
14
12
  Classifier: Programming Language :: Python :: 3.13
15
13
  Classifier: Programming Language :: Python :: 3.14
16
- Requires-Python: >=3.10
14
+ Requires-Python: >=3.12
17
15
  Description-Content-Type: text/markdown
18
16
  License-File: LICENSE
19
17
  Requires-Dist: torch>=2.14.1
20
18
  Requires-Dist: torchvision>=0.29.1
21
- Requires-Dist: diffusers>=0.40.0
19
+ Requires-Dist: diffusers>=0.42.0
22
20
  Requires-Dist: transformers>=5.19.0
23
21
  Requires-Dist: accelerate>=1.15.0
24
22
  Requires-Dist: peft>=0.21.2
@@ -96,7 +94,7 @@ two front ends on it: an **MCP server**, so Claude Code (or any MCP client)
96
94
  can author, run and inspect generations; and a **web UI** for doing the same
97
95
  by hand. A CLI sits underneath for when you want neither.
98
96
 
99
- **Python 3.10-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
97
+ **Python 3.12-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
100
98
 
101
99
  <picture>
102
100
  <source media="(prefers-color-scheme: dark)" srcset="docs/img/ui-workflows-dark.png">
@@ -331,3 +329,4 @@ frame interpolation and more.
331
329
  - [Testing](docs/TESTING.md) — Running the test suite
332
330
  - [Releasing](docs/RELEASING.md) — Cutting a release from a version tag
333
331
  - [Agent Loop](docs/AGENT_LOOP.md) — What the automated implementer/tester ticket labels mean, for anyone joining an Issue
332
+ - [Attributions](docs/ATTRIBUTIONS.md) — Code included from other projects, and the projects whose ideas dw reimplemented
@@ -10,7 +10,7 @@ two front ends on it: an **MCP server**, so Claude Code (or any MCP client)
10
10
  can author, run and inspect generations; and a **web UI** for doing the same
11
11
  by hand. A CLI sits underneath for when you want neither.
12
12
 
13
- **Python 3.10-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
13
+ **Python 3.12-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
14
14
 
15
15
  <picture>
16
16
  <source media="(prefers-color-scheme: dark)" srcset="docs/img/ui-workflows-dark.png">
@@ -245,3 +245,4 @@ frame interpolation and more.
245
245
  - [Testing](docs/TESTING.md) — Running the test suite
246
246
  - [Releasing](docs/RELEASING.md) — Cutting a release from a version tag
247
247
  - [Agent Loop](docs/AGENT_LOOP.md) — What the automated implementer/tester ticket labels mean, for anyone joining an Issue
248
+ - [Attributions](docs/ATTRIBUTIONS.md) — Code included from other projects, and the projects whose ideas dw reimplemented
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffusers-workflow
3
- Version: 0.16.0
3
+ Version: 0.17.0
4
4
  Summary: Declarative workflow engine and web UI for Hugging Face Diffusers
5
5
  Author: dkackman
6
6
  License: Apache-2.0
@@ -8,17 +8,15 @@ Project-URL: Homepage, https://github.com/dkackman/diffusers-workflow
8
8
  Classifier: Development Status :: 3 - Alpha
9
9
  Classifier: Intended Audience :: Developers
10
10
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
11
  Classifier: Programming Language :: Python :: 3.12
14
12
  Classifier: Programming Language :: Python :: 3.13
15
13
  Classifier: Programming Language :: Python :: 3.14
16
- Requires-Python: >=3.10
14
+ Requires-Python: >=3.12
17
15
  Description-Content-Type: text/markdown
18
16
  License-File: LICENSE
19
17
  Requires-Dist: torch>=2.14.1
20
18
  Requires-Dist: torchvision>=0.29.1
21
- Requires-Dist: diffusers>=0.40.0
19
+ Requires-Dist: diffusers>=0.42.0
22
20
  Requires-Dist: transformers>=5.19.0
23
21
  Requires-Dist: accelerate>=1.15.0
24
22
  Requires-Dist: peft>=0.21.2
@@ -96,7 +94,7 @@ two front ends on it: an **MCP server**, so Claude Code (or any MCP client)
96
94
  can author, run and inspect generations; and a **web UI** for doing the same
97
95
  by hand. A CLI sits underneath for when you want neither.
98
96
 
99
- **Python 3.10-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
97
+ **Python 3.12-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
100
98
 
101
99
  <picture>
102
100
  <source media="(prefers-color-scheme: dark)" srcset="docs/img/ui-workflows-dark.png">
@@ -331,3 +329,4 @@ frame interpolation and more.
331
329
  - [Testing](docs/TESTING.md) — Running the test suite
332
330
  - [Releasing](docs/RELEASING.md) — Cutting a release from a version tag
333
331
  - [Agent Loop](docs/AGENT_LOOP.md) — What the automated implementer/tester ticket labels mean, for anyone joining an Issue
332
+ - [Attributions](docs/ATTRIBUTIONS.md) — Code included from other projects, and the projects whose ideas dw reimplemented
@@ -45,6 +45,7 @@ dw/lora_hub.py
45
45
  dw/media.py
46
46
  dw/media_compare.py
47
47
  dw/media_frames.py
48
+ dw/media_readers.py
48
49
  dw/media_types.py
49
50
  dw/notes.py
50
51
  dw/outbound.py
@@ -110,6 +111,7 @@ dw/community_pipelines/pipeline_ltx2_refine.py
110
111
  dw/docs/ACCELERATION.md
111
112
  dw/docs/AGENT_LOOP.md
112
113
  dw/docs/ARCHITECTURE.md
114
+ dw/docs/ATTRIBUTIONS.md
113
115
  dw/docs/DEPENDENCIES.md
114
116
  dw/docs/IP_ADAPTER.md
115
117
  dw/docs/LORAS.md
@@ -135,10 +137,14 @@ dw/pipeline_processors/h3_guide_steps.py
135
137
  dw/pipeline_processors/h3_guides.py
136
138
  dw/pipeline_processors/h3_hold.py
137
139
  dw/pipeline_processors/h3_hold_steps.py
140
+ dw/pipeline_processors/h3_mask.py
141
+ dw/pipeline_processors/h3_mask_cells.py
142
+ dw/pipeline_processors/h3_mask_steps.py
138
143
  dw/pipeline_processors/h3_rules.py
139
144
  dw/pipeline_processors/h3_tiles.py
140
145
  dw/pipeline_processors/mag_calibration.py
141
146
  dw/pipeline_processors/pipeline.py
147
+ dw/pipeline_processors/pipeline_outputs.py
142
148
  dw/pipeline_processors/placement.py
143
149
  dw/pipeline_processors/progress.py
144
150
  dw/pipeline_processors/remote.py
@@ -196,44 +202,44 @@ dw/server/ui/assets/csharp-BKxtCVv1.js
196
202
  dw/server/ui/assets/csp-bTuwJoIa.js
197
203
  dw/server/ui/assets/css-DIMkf-bt.js
198
204
  dw/server/ui/assets/css.worker-C6lDtRpF.js
199
- dw/server/ui/assets/cssMode-Cx99RWkL.js
205
+ dw/server/ui/assets/cssMode-BvFOC5nO.js
200
206
  dw/server/ui/assets/cypher-CVaqCwHa.js
201
207
  dw/server/ui/assets/dart-onAF5SnQ.js
202
208
  dw/server/ui/assets/dockerfile-DZFCIeNp.js
203
209
  dw/server/ui/assets/ecl-D05T4iGw.js
204
210
  dw/server/ui/assets/editor-DjpsE8to.css
205
- dw/server/ui/assets/editor.api-jKhYFhrF.js
211
+ dw/server/ui/assets/editor.api-ChcCMXXR.js
206
212
  dw/server/ui/assets/editor.worker-BmdWdrHZ.js
207
213
  dw/server/ui/assets/elixir-6RTg0lbw.js
208
214
  dw/server/ui/assets/flow9-C5_-GSwl.js
209
- dw/server/ui/assets/freemarker2-Cr_kdwwJ.js
215
+ dw/server/ui/assets/freemarker2-DT2q5NS2.js
210
216
  dw/server/ui/assets/fsharp-C8Ef5oNN.js
211
217
  dw/server/ui/assets/go-C-y9NEjX.js
212
218
  dw/server/ui/assets/graphql-fmXr3nnJ.js
213
- dw/server/ui/assets/handlebars-CnbOycVf.js
219
+ dw/server/ui/assets/handlebars-kaJu_3a1.js
214
220
  dw/server/ui/assets/hcl-CpzslTdj.js
215
- dw/server/ui/assets/html-vCIOVoPc.js
221
+ dw/server/ui/assets/html-BsNsYnSX.js
216
222
  dw/server/ui/assets/html.worker-C5yZDBHz.js
217
- dw/server/ui/assets/htmlMode-B5ESZlHK.js
223
+ dw/server/ui/assets/htmlMode-BcQxv5VO.js
218
224
  dw/server/ui/assets/index-Bm_jBlG4.css
219
- dw/server/ui/assets/index-DIXj1Pp3.js
225
+ dw/server/ui/assets/index-CN0qvKxj.js
220
226
  dw/server/ui/assets/ini-sBoK_t0W.js
221
227
  dw/server/ui/assets/java-BEtHBSE6.js
222
- dw/server/ui/assets/javascript-DpV2UaWD.js
228
+ dw/server/ui/assets/javascript-CEdXynRF.js
223
229
  dw/server/ui/assets/json.worker-DdeUAmHa.js
224
- dw/server/ui/assets/jsonMode-DaGlZZy1.js
230
+ dw/server/ui/assets/jsonMode-hbOYEMCP.js
225
231
  dw/server/ui/assets/julia-Bri6UV-V.js
226
232
  dw/server/ui/assets/kotlin-BOotOW0E.js
227
233
  dw/server/ui/assets/less-B9JPFI3C.js
228
234
  dw/server/ui/assets/lexon-CfSJPG6W.js
229
- dw/server/ui/assets/liquid-Ds835QKV.js
230
- dw/server/ui/assets/lspLanguageFeatures-Cd9OxrIO.js
235
+ dw/server/ui/assets/liquid-JLSoiOSA.js
236
+ dw/server/ui/assets/lspLanguageFeatures-BOyNtxH5.js
231
237
  dw/server/ui/assets/lua-CsQS60Ue.js
232
238
  dw/server/ui/assets/m3-D-oSqn_W.js
233
239
  dw/server/ui/assets/markdown-Cimd5fb3.js
234
- dw/server/ui/assets/mdx-BozOHFIi.js
240
+ dw/server/ui/assets/mdx-sDDXTu9v.js
235
241
  dw/server/ui/assets/mips-CIPQ_RoX.js
236
- dw/server/ui/assets/monaco-673w9Wwq.js
242
+ dw/server/ui/assets/monaco-1MuWdUz9.js
237
243
  dw/server/ui/assets/monaco-n7clI0si.css
238
244
  dw/server/ui/assets/msdax-DauUninz.js
239
245
  dw/server/ui/assets/mysql-SOo6toE5.js
@@ -249,10 +255,10 @@ dw/server/ui/assets/powerquery-D3hlyOfw.js
249
255
  dw/server/ui/assets/powershell-DmHpPYUd.js
250
256
  dw/server/ui/assets/protobuf-C531GsRP.js
251
257
  dw/server/ui/assets/pug-Z5eAx3Zn.js
252
- dw/server/ui/assets/python-D_HjE-WC.js
258
+ dw/server/ui/assets/python-FwMP_5s9.js
253
259
  dw/server/ui/assets/qsharp-DkqhCAOL.js
254
260
  dw/server/ui/assets/r-BwWrilGY.js
255
- dw/server/ui/assets/razor-DjEZAQZw.js
261
+ dw/server/ui/assets/razor-CHr8DUwq.js
256
262
  dw/server/ui/assets/redis-ClamHrr6.js
257
263
  dw/server/ui/assets/redshift-DT7zqm-g.js
258
264
  dw/server/ui/assets/restructuredtext-BYgofb2h.js
@@ -272,15 +278,15 @@ dw/server/ui/assets/swift-Bxkupp3x.js
272
278
  dw/server/ui/assets/systemverilog-Bz4Y3fRF.js
273
279
  dw/server/ui/assets/tcl-DISqw1ZD.js
274
280
  dw/server/ui/assets/ts.worker-DGGa2mF8.js
275
- dw/server/ui/assets/tsMode-B3g7-HAd.js
281
+ dw/server/ui/assets/tsMode-DMRBdzCs.js
276
282
  dw/server/ui/assets/twig-De2hgUGE.js
277
- dw/server/ui/assets/typescript-Bq3yLFs6.js
283
+ dw/server/ui/assets/typescript-DX26K2Zt.js
278
284
  dw/server/ui/assets/typespec-B8J7ngcE.js
279
285
  dw/server/ui/assets/vb-DV3o63ZY.js
280
286
  dw/server/ui/assets/wgsl-DpFanUEy.js
281
- dw/server/ui/assets/workers-Jt2I7Jya.js
282
- dw/server/ui/assets/xml-BD0Sm95a.js
283
- dw/server/ui/assets/yaml-BSnko3ic.js
287
+ dw/server/ui/assets/workers-C00WfVNJ.js
288
+ dw/server/ui/assets/xml-5-4XmnnO.js
289
+ dw/server/ui/assets/yaml-DjHDC-oK.js
284
290
  dw/tasks/assess.py
285
291
  dw/tasks/audio_dynamics.py
286
292
  dw/tasks/audio_handlers.py
@@ -292,6 +298,7 @@ dw/tasks/borders.py
292
298
  dw/tasks/compose_text.py
293
299
  dw/tasks/concat_videos.py
294
300
  dw/tasks/cuts.py
301
+ dw/tasks/cuts_lines.py
295
302
  dw/tasks/depth_estimator.py
296
303
  dw/tasks/diffusion_upscale.py
297
304
  dw/tasks/dissolve_videos.py
@@ -314,18 +321,22 @@ dw/tasks/judge.py
314
321
  dw/tasks/loop_bed.py
315
322
  dw/tasks/lut.py
316
323
  dw/tasks/measure_sync.py
324
+ dw/tasks/mmaudio_decoder.py
317
325
  dw/tasks/model_cache.py
318
326
  dw/tasks/model_handlers.py
319
327
  dw/tasks/pair_audio.py
328
+ dw/tasks/phrases.py
320
329
  dw/tasks/qr_code.py
321
330
  dw/tasks/registry.py
322
331
  dw/tasks/remove_object.py
323
332
  dw/tasks/restore_faces.py
324
333
  dw/tasks/rife_model.py
325
334
  dw/tasks/script_check.py
335
+ dw/tasks/script_findings.py
326
336
  dw/tasks/script_take.py
327
337
  dw/tasks/segment.py
328
338
  dw/tasks/select.py
339
+ dw/tasks/sound_effects.py
329
340
  dw/tasks/speech_generation.py
330
341
  dw/tasks/stabilize.py
331
342
  dw/tasks/task.py
@@ -340,6 +351,11 @@ dw/tasks/voice_attribution.py
340
351
  dw/tasks/weights.py
341
352
  dw/tasks/windows.py
342
353
  dw/tasks/zoe_depth.py
354
+ dw/vendored/__init__.py
355
+ dw/vendored/audio8_tts_model.py
356
+ dw/vendored/mmaudio_clip.py
357
+ dw/vendored/mmaudio_model.py
358
+ dw/vendored/mmaudio_sync_model.py
343
359
  dw/workflows/flux3_klein_upsample.json
344
360
  dw/workflows/flux3_klein_upsample_edit.json
345
361
  dw/workflows/h3_context_ir.json
@@ -367,6 +383,7 @@ dw_mcp/workspaces.py
367
383
  tests/test_admission.py
368
384
  tests/test_admission_capacity.py
369
385
  tests/test_analyze_beats.py
386
+ tests/test_analyze_phrases.py
370
387
  tests/test_api_contract.py
371
388
  tests/test_arch_metrics.py
372
389
  tests/test_arch_report.py
@@ -379,6 +396,7 @@ tests/test_assessment_rules.py
379
396
  tests/test_assets.py
380
397
  tests/test_attention_backend_trace.py
381
398
  tests/test_attention_slicing.py
399
+ tests/test_audio8_tts_model.py
382
400
  tests/test_audio_utils.py
383
401
  tests/test_best_of_n_template.py
384
402
  tests/test_borders.py
@@ -400,6 +418,7 @@ tests/test_concat_videos.py
400
418
  tests/test_config_objects.py
401
419
  tests/test_configuration_schema.py
402
420
  tests/test_content_types.py
421
+ tests/test_cost_scaling_h3_frames.py
403
422
  tests/test_dependencies_declared.py
404
423
  tests/test_depth_estimator.py
405
424
  tests/test_device.py
@@ -425,6 +444,7 @@ tests/test_fit_to_model.py
425
444
  tests/test_flux3_catalog.py
426
445
  tests/test_for_each.py
427
446
  tests/test_forget_workspace_history.py
447
+ tests/test_fractional_fps.py
428
448
  tests/test_gallery_roles.py
429
449
  tests/test_gather.py
430
450
  tests/test_grade.py
@@ -436,6 +456,7 @@ tests/test_h3_context_ir.py
436
456
  tests/test_h3_guides.py
437
457
  tests/test_h3_hold_audio.py
438
458
  tests/test_h3_latent_upscale.py
459
+ tests/test_h3_mask.py
439
460
  tests/test_h3_refine.py
440
461
  tests/test_h3_rules.py
441
462
  tests/test_h3_schedule.py
@@ -506,7 +527,11 @@ tests/test_media_decode_threads.py
506
527
  tests/test_media_frames.py
507
528
  tests/test_media_info.py
508
529
  tests/test_media_layering.py
530
+ tests/test_media_sample_frames.py
509
531
  tests/test_mix_audio.py
532
+ tests/test_mmaudio_decoder.py
533
+ tests/test_mmaudio_model.py
534
+ tests/test_mmaudio_sync_model.py
510
535
  tests/test_model_cache.py
511
536
  tests/test_modular_output_properties.py
512
537
  tests/test_modular_pipeline.py
@@ -531,6 +556,7 @@ tests/test_pipeline_caching.py
531
556
  tests/test_pipeline_components.py
532
557
  tests/test_plan.py
533
558
  tests/test_plan_cuts.py
559
+ tests/test_plan_cuts_phrases.py
534
560
  tests/test_plugin_skills.py
535
561
  tests/test_prepare_pipeline.py
536
562
  tests/test_previous_result_walker_parity.py
@@ -597,6 +623,7 @@ tests/test_shaping_logs.py
597
623
  tests/test_shot_span_preflight.py
598
624
  tests/test_shots.py
599
625
  tests/test_slice_preflight.py
626
+ tests/test_sound_effects.py
600
627
  tests/test_sparse_attention_backends.py
601
628
  tests/test_sparse_attention_processor.py
602
629
  tests/test_sparse_attention_tiles.py
@@ -1,6 +1,6 @@
1
1
  torch>=2.14.1
2
2
  torchvision>=0.29.1
3
- diffusers>=0.40.0
3
+ diffusers>=0.42.0
4
4
  transformers>=5.19.0
5
5
  accelerate>=1.15.0
6
6
  peft>=0.21.2
@@ -110,9 +110,9 @@ except ImportError as e:
110
110
 
111
111
 
112
112
  def _read_version():
113
- # Single-sourced from pyproject.toml. Read as text rather than TOML:
114
- # tomllib is 3.11+ and this project supports 3.10. In a wheel install
115
- # there is no pyproject on disk - the package metadata carries it.
113
+ # Single-sourced from pyproject.toml. A regex on the text is enough for
114
+ # one line, without parsing the whole file. In a wheel install there is
115
+ # no pyproject on disk - the package metadata carries it.
116
116
  try:
117
117
  pyproject = os.path.join(os.path.dirname(__file__), "..", "pyproject.toml")
118
118
  with open(pyproject, encoding="utf-8") as f:
@@ -914,7 +914,9 @@ def resolve_relative_path(path, base_dir):
914
914
  # frame list first dropped the soundtrack they measure and failed every probe
915
915
  # on an asset:/output: video (#387) - and window_video, which cuts the
916
916
  # source's soundtrack with its frames and so reads the file with its audio
917
- # (#601) - and trim_video, which cuts a soundtrack the same way (#627) - see _realize_lazy_frame_arguments
917
+ # (#601) - and trim_video, which cuts a soundtrack the same way (#627) - and
918
+ # generate_sound_effects, which samples the file at its own rates (#1133) - see
919
+ # _realize_lazy_frame_arguments
918
920
  _LAZY_FRAME_COMMANDS = frozenset(
919
921
  {
920
922
  "get_frame",
@@ -925,6 +927,7 @@ _LAZY_FRAME_COMMANDS = frozenset(
925
927
  "analyze_sync_drift",
926
928
  "window_video",
927
929
  "trim_video",
930
+ "generate_sound_effects",
928
931
  }
929
932
  )
930
933
 
@@ -16,13 +16,15 @@ permissive beyond the MIME-shape check: their writer dispatch is a generic
16
16
  prefix/suffix match (PIL's own format inference, a literal text or JSON
17
17
  write) with no narrower container to enforce a whitelist against.
18
18
 
19
- The one text/* exception is active content. `/outputs` serves a written
20
- file on the UI's own origin, without a token, so an .html or .xml output is
21
- a page whose script reads the API token the UI keeps in localStorage (#407).
22
- `text/html` and `text/xml` are the two active types the text writer can
23
- produce, so they are refused outright; the server also serves every active
24
- type it finds on disk under a `Content-Security-Policy: sandbox`, since a
25
- planted file never passes through here.
19
+ The one exception is active content. `/outputs` serves a written file on
20
+ the UI's own origin, without a token, so an .html, .xml or .svg output is a
21
+ page whose script reads the API token the UI keeps in localStorage (#407).
22
+ Every type in `ACTIVE_DOCUMENT_TYPES` is refused outright, whichever writer
23
+ would take it - refusing only the two the text writer produces left
24
+ `application/xml`, `application/xhtml+xml` and `image/svg+xml` stopped by
25
+ nothing but a result-type mismatch (SE-F035). The same set is what the
26
+ server serves under a `Content-Security-Policy: sandbox` when it finds one on
27
+ disk, since a planted file never passes through here.
26
28
  """
27
29
 
28
30
  import logging
@@ -67,8 +69,18 @@ LOSSY_AUDIO_CONTENT_TYPES = {
67
69
  # The only container encode_video writes - it always encodes h264 video
68
70
  MUXED_VIDEO_CONTENT_TYPE = "video/mp4"
69
71
 
70
- # Result types a browser would run as a document on the UI origin
71
- REFUSED_ACTIVE_CONTENT_TYPES = frozenset({"text/html", "text/xml"})
72
+ # Types a browser renders as a document, where script runs: refused as a
73
+ # result type here, and served under a CSP sandbox by /outputs and /inputs
74
+ # (dw/server/routes/files.py)
75
+ ACTIVE_DOCUMENT_TYPES = frozenset(
76
+ {
77
+ "text/html",
78
+ "application/xhtml+xml",
79
+ "text/xml",
80
+ "application/xml",
81
+ "image/svg+xml",
82
+ }
83
+ )
72
84
 
73
85
 
74
86
  def _active_content_fault(value):
@@ -76,7 +88,7 @@ def _active_content_fault(value):
76
88
  # the same document type
77
89
  if (
78
90
  isinstance(value, str)
79
- and value.split(";", 1)[0].strip().lower() in REFUSED_ACTIVE_CONTENT_TYPES
91
+ and value.split(";", 1)[0].strip().lower() in ACTIVE_DOCUMENT_TYPES
80
92
  ):
81
93
  return (
82
94
  f"Invalid content_type: {value!r} - active content is not written: "
@@ -160,7 +172,7 @@ def refuse_active_content_type(value):
160
172
 
161
173
 
162
174
  __all__ = [
163
- "REFUSED_ACTIVE_CONTENT_TYPES",
175
+ "ACTIVE_DOCUMENT_TYPES",
164
176
  "content_type_errors",
165
177
  "content_type_fault",
166
178
  "guess_extension",
@@ -33,15 +33,16 @@ one to open.
33
33
  | Step progress | `dw/pipeline_processors/progress.py`: `reported_progress_bars` | A pipeline with no step callback reports its denoise steps through its progress bars. | `tests/test_modular_progress.py::test_every_advance_of_the_bar_is_reported` |
34
34
  | Step timing | `dw/pipeline_processors/timing.py`: `StepTimer`, `step_timer`, `timed_step`, `mark` | Only a pipeline step that ran is timed, on the worker's monotonic clock: `step_timer` opens a `StepTimer` for a step with a `pipeline` or `pipeline_reference` and None for any other, which also hides an outer step's timer from a composed child. Load, call, denoise start, each pass and save reach the open timer through `mark`, and nowhere else. Denoise start is never taken inside a compiled region: a whole-compiled denoiser (`_compiled_call_impl` set) has that callable wrapped for the call instead of a forward pre-hook, which `fullgraph: true` cannot trace. A span with a missing mark is null, never guessed. `record_step` puts the reading on the step's manifest entry and `step_end`, and a reused step gets no `timing`. A chain sums its pipeline calls into one `timing` with `segments: N`. `ManifestEntry.timing` declares the shape (`docs/WORKSPACES.md` *Step timing*). | `tests/test_step_timing.py::test_a_missing_denoise_start_nulls_encode_and_first_pass`, `tests/test_step_timing.py::test_a_reused_step_carries_no_timing_even_when_one_is_passed`, `tests/test_step_timing.py::test_a_chain_sums_its_segments_and_takes_one_median_over_both`, `tests/test_step_timing.py::test_a_task_step_run_through_the_step_loop_has_no_timing`, `tests/test_step_timing.py::test_the_denoise_hook_marks_the_first_forward_once_and_removes_itself`, `tests/test_step_timing.py::test_a_fullgraph_compiled_denoiser_runs_and_still_gets_the_start_mark` |
35
35
  | Step-cache skip counts | `dw/pipeline_processors/timing.py`: `CacheCounter`, `counting_forwards`, `report_cache_stats`, `StepTimer.cache_counted`; `dw/pipeline_processors/components.py`: `stateful_cache_context`; `dw/pipeline_processors/mag_calibration.py`: `get_cache_transformer`, `captured_mag_calibration` | For `first_block` and `mag`, a forward hook on the cache transformer counts computed or skipped once per forward, reading the leader hook's `should_compute` inside the cond/uncond `cache_context` the pipeline opened, so classifier-free guidance counts both forwards. `stateful_cache_context` registers the hook for one pipeline call; its `finally` emits `cache_stats` before `_reset_stateful_cache()` and removes the hook after the event. Private diffusers state that has moved gives null counts and one `cache_stats_unavailable` warning, and never fails the run; `taylorseer`, `faster` and `text_kv` report type and config only, with no warning. The denoiser a cache attaches to (`get_cache_transformer`) and the MagCache calibration capture (`captured_mag_calibration`, the end-of-run log record turned into `cache_stats`-side job events, #891/#927) live in `mag_calibration.py`, which `components.py` imports and re-exports for `pipeline.py`, never the reverse. The counts reach the step's `timing.cache` only through `StepTimer.cache_counted`; a chain sums its calls' counts, and a null in any call nulls the sum. A step with no `cache` has no `cache` key and no event (`docs/ACCELERATION.md` *Reading the skip counts*). | `tests/test_cache_stats.py::test_cfg_counts_two_forwards_per_step_and_they_add_up`, `tests/test_cache_stats.py::test_the_event_names_the_step_and_segment_and_goes_out_before_the_reset`, `tests/test_cache_stats.py::test_moved_hook_state_nulls_the_counts_warns_once_and_the_run_finishes`, `tests/test_cache_stats.py::test_the_private_diffusers_names_are_where_the_counter_reads_them`, `tests/test_cache_stats.py::test_the_timer_sums_counts_and_nulls_on_any_null`, `tests/test_cache_stats.py::test_types_without_a_decision_report_type_only_and_no_warning` |
36
+ | Vendored model ports | `dw/vendored/` (`audio8_tts_model.py`, `mmaudio_model.py`, `mmaudio_sync_model.py`, `mmaudio_clip.py`) | Upstream model code dw carries is one module per port, pinned to the commit or Hub revision its docstring names, so it can be diffed against its source and re-pinned as a unit; a port reaches dw only for the validated media loaders and is imported only by the task that runs it. Like `dw/community_pipelines/`, the package is outside the architecture ratchet (`EXCLUDED` in `scripts/arch_metrics.py`): a port keeps upstream's shape, which the module and function ceilings are not written for. | `tests/test_arch_metrics.py::test_vendored_model_ports_are_not_counted`, `tests/test_mmaudio_model.py::test_modules_are_imported_only_by_the_sound_effects_task`, `tests/test_mmaudio_sync_model.py::test_module_is_imported_only_by_the_sound_effects_task` |
36
37
  | Community pipelines | `dw/community_pipelines/` (e.g. `pipeline_ltx2_refine.py`: `LTX2RefinePipeline`), `dw/introspection.py`: `community_pipelines`, `load_allowed_class` | A pipeline dw ships is named by its dotted path (`dw.community_pipelines.<module>.<Class>`), loads untrusted because it is under `dw`, and is listed by `list_pipelines` and resolved by `get_pipeline_signature` - only the modules in that directory, never a caller-chosen import. `LTX2RefinePipeline` VAE-encodes `video` at `width` x `height` and passes it unnormalized as `latents`, because `LTX2Pipeline.prepare_latents` normalizes 5-D latents itself. | `tests/test_ltx2_refine_pipeline.py::TestIntrospection::test_only_the_shipped_modules_resolve`, `tests/test_ltx2_refine_pipeline.py::TestEncode::test_the_latents_are_left_unnormalized_for_the_parent` |
37
38
  | Adding a task | `dw/tasks/registry.py`: `register_command`, `RegistryTable` | A task is a function registered with `@register_command`, and the signature of its implementation is its argument schema. Its validate-time rules are declared on the same decorator - `domains`, `choices`, `static_check`, `whole_numbers` and `media_arguments` - and `TASK_ARGUMENT_DOMAINS`, `TASK_ARGUMENT_CHOICES`, `TASK_STATIC_CHECKS`, `TASK_WHOLE_NUMBER_ARGUMENTS` and `TASK_MEDIA_ARGUMENTS` are read-only views derived from them, so there is no second table to forget (#692). The registry lives in `dw/tasks/registry.py`; `dw/tasks/task.py` re-exports it, and a task module may register its own handler, as `dw/tasks/beats.py` does, provided `dw/tasks/task.py` imports it (`docs/TASKS.md` *Adding a task*). The built-in handlers are grouped by family the same way - `dw/tasks/audio_handlers.py`, `dw/tasks/video_handlers.py`, `dw/tasks/finish_handlers.py` and `dw/tasks/model_handlers.py` (#790) - and `dw/tasks/task.py` keeps the general-purpose commands, the processor dispatch and `Task`. | `tests/test_task_discovery.py::TestDescribeTask::test_signature_becomes_the_schema`, `tests/test_task_registry_rules.py::test_every_derived_table_is_the_registrys_view`, `tests/test_task_registry_rules.py::test_every_static_check_is_registered_to_exactly_one_command`, `tests/test_task_registry_rules.py::test_every_media_argument_is_a_parameter_of_its_command` |
38
- | Task argument domains | `dw/task_domains.py`: `check_arguments`, `task_argument_errors`; `dw/task_problems.py`: `face_track_errors`, `beats_errors`, `cuts_errors`, `lut_errors` | A numeric domain that a signature cannot express is declared on the command's `@register_command(domains=...)`, and it is checked at validation and again at run time. A numeric argument is read by `whole_number` or `real_number`, the only numeric coercion in `dw/tasks/`, and validation applies the same rule (`number_problem`), so a value is refused at both or at neither: `"3.0"` is a whole number, `"3.5"` for one of `whole_numbers` is not, and `true` is no number (#774). `Task.run` coerces every declared argument through `coerce_arguments` before dispatch, so a handler sees a number, and an argument that has no range besides being a number declares `finite`. A command's cross-argument rules are its registered `static_check`, which `task_argument_errors` runs at validation (`attribute_voices`' `voices_argument_errors`, kept in `dw/tasks/voice_attribution.py`, among them). A literal enum choice (`choice_errors`) is refused at validation by the same module. The per-family rules past a single domain live in `dw/task_problems.py`, which reads `task_domains`' helpers and is never imported by it (`task_argument_errors` reaches them only through the registered `static_check`, so `import_cycles` stays 0; #790): the `ingredients_grid` image count against `max_images` (`ingredients_grid_errors`), and `crop_face_track`'s cross-argument rules (`face_track_problems`, `face_track_errors`: crop size a multiple of the step's `multiple` (32 by default), `remainder` below `modulus`, `gate_zero` above `gate_full`, padding and confidence limits), which the task checks again at run time, as `analyze_beats`' are too (`beats_problems`, `beats_errors`: `min_bpm` below `max_bpm`, and anchors that are one kind per list, ascending, with whole beat indexes; `tests/test_analyze_beats.py`), and `plan_cuts`' (`cuts_problems`, `cuts_errors`: a bare-string transcript (`transcript_problem`, which `plan_cuts` also calls at run time), `min_scene_s` above `max_scene_s`, `segment_by: "beat"` without beats), and `apply_lut`'s (`lut_source_problem`, `palette_problem`, `lut_errors`: exactly one of `lut` or `palette`, and a palette of 2..16 `#rrggbb` colours, re-checked at run time by `check_lut_source`), and `check_face_detector_source` vets its Hub repo and `.onnx` file before any download. `select`'s index stays in `task_domains` with the other media-timing rules (`select_index_problem`, `select_rule_problems`: a whole number, at least 0, and below the candidate count when the count is known, i.e. at run time or when `candidates` is a written list). | `tests/test_task_domains.py::TestTheStaticPass::test_a_negative_frame_count_is_refused_at_its_path`, `tests/test_numeric_coercion.py::TestGradeExposure::test_a_string_number_grades_like_the_number`, `tests/test_task_domains.py::TestAtRunTime::test_slice_audio_refuses_a_negative_count`, `tests/test_ingredients_grid.py::TestStaticValidation::test_bad_layout_and_fit`, `tests/test_face_track.py::TestStaticValidation::test_bad_literal_is_an_error_at_its_argument`, `tests/test_face_track.py::TestCropFaceTrack::test_bad_arguments_are_refused_at_run_time`, `tests/test_face_track.py::TestStaticValidation::test_a_declared_grid_is_accepted`, `tests/test_face_track.py::TestDetectorSource::test_traversing_repo_is_refused`, `tests/test_select_validation.py::TestSelectErrors::test_an_out_of_range_literal_index_names_both_ends`, `tests/test_lut.py::TestPaletteAtValidate::test_both_refuse_naming_the_two`, `tests/test_lut.py::TestPalette::test_a_bad_palette_refuses_naming_the_entry` |
39
+ | Task argument domains | `dw/task_domains.py`: `check_arguments`, `task_argument_errors`; `dw/task_problems.py`: `face_track_errors`, `beats_errors`, `cuts_errors`, `lut_errors` | A numeric domain that a signature cannot express is declared on the command's `@register_command(domains=...)`, and it is checked at validation and again at run time. A numeric argument is read by `whole_number` or `real_number`, the only numeric coercion in `dw/tasks/`, and validation applies the same rule (`number_problem`), so a value is refused at both or at neither: `"3.0"` is a whole number, `"3.5"` for one of `whole_numbers` is not, and `true` is no number (#774). `Task.run` coerces every declared argument through `coerce_arguments` before dispatch, so a handler sees a number, and an argument that has no range besides being a number declares `finite`. A command's cross-argument rules are its registered `static_check`, which `task_argument_errors` runs at validation (`attribute_voices`' `voices_argument_errors`, kept in `dw/tasks/voice_attribution.py`, among them). A literal enum choice (`choice_errors`) is refused at validation by the same module. The per-family rules past a single domain live in `dw/task_problems.py`, which reads `task_domains`' helpers and is never imported by it (`task_argument_errors` reaches them only through the registered `static_check`, so `import_cycles` stays 0; #790): the `ingredients_grid` image count against `max_images` (`ingredients_grid_errors`), and `crop_face_track`'s cross-argument rules (`face_track_problems`, `face_track_errors`: crop size a multiple of the step's `multiple` (32 by default), `remainder` below `modulus`, `gate_zero` above `gate_full`, `max_frames` at or above `min_frames`, padding and confidence limits), which the task checks again at run time, as `analyze_beats`' are too (`beats_problems`, `beats_errors`: `min_bpm` below `max_bpm`, and anchors that are one kind per list, ascending, with whole beat indexes; `tests/test_analyze_beats.py`), and `plan_cuts`' (`cuts_problems`, `cuts_errors`: a bare-string transcript (`transcript_problem`, which `plan_cuts` also calls at run time), `min_scene_s` above `max_scene_s`, `segment_by: "beat"` without beats), and `apply_lut`'s (`lut_source_problem`, `palette_problem`, `lut_errors`: exactly one of `lut` or `palette`, and a palette of 2..16 `#rrggbb` colours, re-checked at run time by `check_lut_source`), and `check_face_detector_source` vets its Hub repo and `.onnx` file before any download. `select`'s index stays in `task_domains` with the other media-timing rules (`select_index_problem`, `select_rule_problems`: a whole number, at least 0, and below the candidate count when the count is known, i.e. at run time or when `candidates` is a written list). | `tests/test_task_domains.py::TestTheStaticPass::test_a_negative_frame_count_is_refused_at_its_path`, `tests/test_numeric_coercion.py::TestGradeExposure::test_a_string_number_grades_like_the_number`, `tests/test_task_domains.py::TestAtRunTime::test_slice_audio_refuses_a_negative_count`, `tests/test_ingredients_grid.py::TestStaticValidation::test_bad_layout_and_fit`, `tests/test_face_track.py::TestStaticValidation::test_bad_literal_is_an_error_at_its_argument`, `tests/test_face_track.py::TestCropFaceTrack::test_bad_arguments_are_refused_at_run_time`, `tests/test_face_track.py::TestStaticValidation::test_a_declared_grid_is_accepted`, `tests/test_face_track.py::TestDetectorSource::test_traversing_repo_is_refused`, `tests/test_select_validation.py::TestSelectErrors::test_an_out_of_range_literal_index_names_both_ends`, `tests/test_lut.py::TestPaletteAtValidate::test_both_refuse_naming_the_two`, `tests/test_lut.py::TestPalette::test_a_bad_palette_refuses_naming_the_entry` |
39
40
  | Variables | `dw/variables.py`: `set_variables`, `argument_errors`, `resolve_variable_values` | `argument_errors` folds a caller's arguments in exactly as `set_variables` does when a run starts, so a bad name or value is refused before anything is queued. | `tests/test_variables.py::test_argument_errors_reports_a_dict_passed_for_a_string_variable` |
40
41
  | List variables from the CLI | `dw/run.py`, `dw/variables.py`: `get_value` | A `name=value` string given for a list variable is split on commas, so a list of objects can only be passed as JSON over the API or MCP. | `tests/test_variables.py::test_set_variables_list_default_splits_on_comma` |
41
42
  | `for_each` expansion | `dw/for_each.py`: `expand_for_each`, `group_of` | Each entry becomes an ordinary step named `<step>@<entry>`, after substitution and before the reference check. | `tests/test_for_each.py::TestNaming::test_member_name_joins_with_at` |
42
43
  | Optional entry field | `dw/for_each.py`: `_optional_item`, `_item_fields` | `{"item": "field", "default": X}` reads an entry field with a fallback; without `default` it is the plain required read, and `list_fields` / `entry_field_warnings` count the field as one entries take. The editor's string scan needs no twin code, only the shared case file. | `tests/test_for_each.py::TestOptionalItem::test_a_present_field_wins_and_an_absent_one_takes_the_default`, `tests/test_ui_twins.py::test_the_engine_decides_each_shared_reference_case` |
43
44
  | Previous results | `dw/previous_results.py`: `get_iterations`, `previous_result_reference_errors` | Several `previous_result:` references in one step multiply into a cartesian product. | `tests/test_previous_results.py::TestGetIterations::test_multiple_references_create_cartesian_product` |
44
- | Previous-result check | `dw/previous_results.py`: `previous_result_reference_errors` | A literal reference to a step that is not earlier in the workflow is a validation error. | `tests/test_previous_results.py::TestStaticReferenceChecking::test_a_step_cannot_reference_itself_or_a_later_one` |
45
+ | Previous-result check | `dw/previous_results.py`: `previous_result_reference_errors`, `cross_entry_reference_errors`; the sibling rule is `dw/for_each.py`: `cross_entry_key` (beside `group_of`, which it calls), which the cross-entry check, the earlier-step check and `dw/video_extensions.py`: `video_into_image_errors` all ask | A literal reference to a step that is not earlier in the workflow is a validation error. A for_each member reading another entry of its own list (`shot@a` inside `shot@b`, either spelling, any `.property`) is a validation error too, `cross_entry_reference_errors` (#1101); same-key pairing, other groups and `gather:` stay legal. | `tests/test_previous_results.py::TestStaticReferenceChecking::test_a_step_cannot_reference_itself_or_a_later_one`, `tests/test_previous_results.py::TestCrossEntryReferences::test_the_prefix_spelled_in_an_entry_is_refused` |
45
46
  | Type conversion | `dw/arguments.py`: `realize_args`, `dw/type_helpers.py`: `get_type` | A key ending `_type` or `_dtype` loads a Python object at realize time. The other spellings, and `{}` escaping, are in `docs/WORKFLOW_GUIDE.md`. | `tests/test_type_helpers.py::TestGetType::test_get_type_from_diffusers`, `tests/test_arguments.py::TestRealizeArgs::test_realize_escaped_type_reference` |
46
47
 
47
48
  ## References and libraries
@@ -75,6 +76,7 @@ one to open.
75
76
  | Result subfolders | `dw/subfolders.py`: `subfolder_errors`, `dw/security.py`: `SUBFOLDER_PATTERN` | A step's `result.subfolder` is checked for shape at validation. | `tests/test_subfolders.py::TestValidationErrorsIntegration::test_validation_errors_reports_a_bad_subfolder` |
76
77
  | Template subfolder roles | `workflows/templates/`, `dw/workflows/` | Every saving step of a template is marked `final` or `intermediate`, with at least one `final`, and packaged builtins stay unmarked. | `tests/test_template_subfolders.py::test_every_saving_step_of_a_template_names_its_role`, `tests/test_template_subfolders.py::test_the_packaged_builtins_stay_unmarked` |
77
78
  | Frames carrying their rate | `dw/media_types.py`: `FrameList` (re-exported by `dw/tasks/video_utils.py`), `rated_videos` | The one list of frames (or of videos) that carries `.fps` and `.shots`: a video loaded from a file (`dw/argument_media.py`) and a step that knows its rate but would return bare frame lists both answer it - `h3_tiles`' tiled refine `videos`, and every pipeline step whose pipeline reports its own `fps` (MiniMax-H3's property; `dw/output_extraction.py`: `attach_video_frame_rate`, called by `pipeline.py`'s `_run_once` beside `attach_audio_sample_rate`, #1056) - through `rated_videos`, the batch and each video in it, so `pair_audio` and the result writer read `getattr(video, "fps", None)` instead of fitting and playing at the default 8 fps. A pipeline that reports no rate leaves its lists bare. No second class of that name. | `tests/test_h3_tiles.py::TestTileLoopReporting::test_the_videos_are_dws_one_frame_list`, `tests/test_pipeline_components.py::TestVideoFrameRate::test_a_dict_outputs_videos_carry_the_pipelines_rate`, `tests/test_pipeline_components.py::TestVideoFrameRate::test_a_pipeline_with_no_rate_leaves_the_lists_bare`, `tests/test_modular_output_properties.py::TestTheBasesOwnTakeSavesBesideIt::test_the_base_take_pairs_at_its_own_rate_with_no_padding`, `tests/test_video_utils.py` (the `FrameList` cases) |
79
+ | Writing a video at its rate | `dw/writers.py`: `encode_video`, `exact_frame_rate` | A fractional rate is written as the exact rational (30000/1001, 24000/1001, 60000/1001), never truncated to a whole rate, and no `dw/` or `dw_mcp/` module imports `encode_video` from `diffusers.utils` - every audio-carrying video write goes through `dw.writers.encode_video` (`dw/result.py`, `dw/pipeline_processors/chain.py`). A declared fractional `result.fps` is therefore accepted by `fps_errors`. | `tests/test_fractional_fps.py::test_encode_video_with_audio_keeps_fractional_rate`, `tests/test_fractional_fps.py::test_no_dw_module_calls_the_diffusers_encode_video_directly`, `tests/test_fractional_fps.py::test_the_diffusers_hook_the_wrapper_swaps_still_exists` |
78
80
  | JSON records beside media | `dw/media_types.py`: `JsonRecord`, `dw/result.py`: `Result.save_artifact` | A dict marked `JsonRecord` is saved whole as one `.json`, whatever content type the step declares, and is never split into one file per key. | `tests/test_face_track.py::test_json_record_is_saved_whole_under_a_video_content_type`, `tests/test_face_track.py::test_the_task_result_saves_crops_as_video_and_track_as_one_json` |
79
81
  | Reading a JSON record back | `dw/locations.py`: `load_json_record` | A task reads a saved JSON record (`fit_to_model`'s, `crop_face_track`'s) only through `load_json_record`: the path is confined like any media path, then the extension must be `.json`, then the size is checked against `MAX_JSON_SIZE`, and only then is it parsed. `fit._read_fit` and `face_track._read_track` call it, never `open`. | `tests/test_locations.py::TestLoadJsonRecord::test_traversal_out_of_the_roots_is_refused`, `tests/test_locations.py::TestLoadJsonRecord::test_a_non_json_extension_is_refused`, `tests/test_locations.py::TestLoadJsonRecord::test_an_oversized_file_is_refused_before_it_is_read`, `tests/test_fit_to_model.py::TestRestore::test_fit_path_with_traversal_is_refused` |
80
82
  | Shots in a joined video | `dw/shots.py` | Every `AudioVideo` constructor decides what to do with `shots`, and the sample spans are measured from the joined waveform. | `tests/test_shots.py::test_every_audio_video_constructor_site_is_decided`, `tests/test_shots.py::TestConcatVideosShots::test_an_overrun_track_is_measured_not_derived` |
@@ -98,7 +100,7 @@ one to open.
98
100
  | Variable constraints | `dw/variable_constraints.py`: `apply_constraints`; the grid arithmetic `aligned` / `aligned_down` | A model's rule about a value is declared in the workflow's `variable_constraints`, and it is checked at validation and again before anything loads. `plan_cuts` (and its static check) rounds render lengths through `aligned` / `aligned_down`, never its own copy, so a planned `num_frames` is one the template's constraint accepts; `crop_face_track` pads its crops to the step's `modulus`/`remainder` grid through `aligned` too (`padding_to_grid`). | `tests/test_variable_constraints.py::TestTheGrid::test_without_snap_an_off_grid_value_is_refused_not_rounded`, `tests/test_variable_constraints.py::TestTheGrid::test_plan_cuts_rounds_through_the_constraint_owner`, `tests/test_face_track.py::TestPadding::test_padding_to_grid_rounds_through_the_constraint_owner`, `tests/test_variable_constraints.py::TestTheRunTimePass::test_an_illegal_value_is_refused_before_anything_loads` |
99
101
  | Bound acknowledgement | `dw/plan.py`: `fingerprint`, `dw/server/admission.py`: `check_bound_acknowledgement` | A bound `acknowledged_cost` is refused with 409 when the plan's fingerprint or its required downloads changed. The fingerprint is keyed only by what can change the output: `DOCUMENTATION_KEYS` (`cost`, `cost_drivers`, `vram_estimate`, descriptions, catalog shape/traits), a constraint's `reason` and a result's role, subfolder and file name are left out, of the workflow and of each composed child; every schema key is sorted into left out or kept. A number digests by value, not spelling (`12.0` as `12`), and the seed stays out (#85). | `tests/test_plan.py::TestFingerprintKeys::test_the_exclusion_lists_are_pinned`, `tests/test_plan.py::TestTheCatalogH3Template::test_a_client_round_trip_keeps_it`, `tests/test_plan.py::TestFingerprintKeys::test_every_top_level_schema_key_is_sorted`, `tests/test_server.py::TestBoundRerun::test_a_rerun_bound_to_a_stale_plan_is_refused`, `tests/test_server.py::TestBoundAcknowledgement::test_a_matching_fingerprint_queues` |
100
102
  | Per-repo gating | `dw/plan_downloads.py`: `_model_info`, `_probe_gate_blocked`, assembled by `dw/plan.py`: `build_plan` | Each gated repo, including a `loras` entry's repo, is probed and reported on its own. | `tests/test_plan.py::TestDownloadsRequired::test_a_gated_repo_this_token_lacks_access_to_is_blocked` |
101
- | Download sources | `dw/plan_downloads.py`: `downloads_required`, `_collect_sources`, `_collect_component_overrides`, `_sub_workflow_paths` (which `plan.estimate` walks children by too; the module never imports `dw/plan.py` back, and `plan.py` re-exports `downloads_required` and `gate_warnings`) | `downloads_required` lists every `model_name`, `loras` repo, single-file URL and `load_components.pretrained_model_name_or_path` override (string, per-component dict, `default`), once each. The base repo stays listed whole: an override's replaced subfolder is not subtracted, so the list is a floor. | `tests/test_plan.py::TestDownloadsRequired::test_a_load_components_repo_override_is_listed` |
103
+ | Download sources | `dw/plan_downloads.py`: `downloads_required`, `_collect_sources`, `_collect_component_overrides`, `_sub_workflow_paths` (which `plan.estimate` walks children by too; the module never imports `dw/plan.py` back, and `plan.py` re-exports `downloads_required` and `gate_warnings`) | `downloads_required` lists every `model_name`, `loras` repo (a `loras` entry naming a resolved `weight_name` is listed instead as a `{repo, filename, revision}` file entry built by `file_entries`, sized as that file), single-file URL and `load_components.pretrained_model_name_or_path` override (string, per-component dict, `default`), once each. The base repo stays listed whole: an override's replaced subfolder is not subtracted, so the list is a floor. | `tests/test_plan.py::TestDownloadsRequired::test_a_load_components_repo_override_is_listed` |
102
104
  | Task weights | each fetching task's `*_source(arguments)` (e.g. `dw/tasks/remove_object.py`: `remover_source`); `dw/tasks/weights.py`: `argument_or_default`, `file_entries`, `package_dir`; `dw/tasks/registry.py`: `required_weights_hook`, `register_weights_fallback`; `dw/tasks/image_utils.py`: `processor_weights_hook`; `dw/security.py`: `validate_weight_name`; `dw/plan_downloads.py`: `_collect_task_weights`, `_file_info` | A model-backed task declares `required_weights(arguments)` on its `register_command`, and `downloads_required` lists those repos beside the pipeline `model_name`s (a shared repo once; a reference or local-path argument none). A single-file task lists `{repo, filename, revision}` entries, checked per file against the cache; `restore_faces` also lists facexlib's weights as URL entries. A task's declaration and its loader read the same resolution of which argument wins (a single-file task's `*_source(arguments)`, an overridable whole-repo task's `argument_or_default` call, a fixed repo's module constant), so they cannot differ; `argument_or_default` is the shared helper only where `None` means the default (`remover_source` and `upscaler_source` treat any falsy value as absent; `spandrel_source` has no default). `file_entries` builds a file entry (its name checked by `validate_weight_name`), `package_dir` finds facexlib's weights dir without importing it, and `_file_info` sizes one file. The lookup path is acyclic: `dw/locations.py` reads the registry's tables and the task modules import the location policy and `weights.py`, so the registry imports no task module (an image processor's hook reaches it through `register_weights_fallback`, which `image_utils` calls at import) and `weights.py` imports only `dw/security.py`, where `validate_weight_name` lives for that reason. A task module the hook lookup imports keeps `transformers` out of its module top (`hf_pipeline` is a lazy wrapper, patched by name in the tests), so a validate never pays for it. | `tests/test_task_weights.py`, `tests/test_task_weights.py::TestTheHookPathStaysAcyclic::test_weights_imports_only_the_security_leaf_from_dw`, `tests/test_task_weights.py::TestTheHookPathStaysAcyclic::test_the_registry_imports_nothing_from_dw` |
103
105
  | Observed cost | `dw/server/observed_cost.py`: `declared_drivers`, `ObservedCosts._on_this_card`, `ObservedCosts.card` | `observed` comes only from this box's finished jobs on the named card (the one `route` names, for `plan.estimate`), else the server's own card; `ObservedCosts.card` owns a card's (kind, name, default). Rows are matched by card name whatever index they ran on (a job from before jobs carried a `device` counts only while the server is on the default card), and never writes `cost`. Cold and warm runs are reported separately. | `tests/test_observed_cost.py::TestColdIsNotWarm::test_the_two_are_reported_separately_each_with_its_runs`, `tests/test_observed_cost.py::TestByCard::test_only_rows_from_this_card_count_whichever_index_they_had`, `tests/test_observed_cost.py::TestByCard::test_rows_from_before_jobs_carried_a_device_do_not_count_off_the_default_card` |
104
106
  | The estimate | `dw/plan.py`: `estimate`, `_tempered`; the driver scaling is `dw/cost_scaling.py`: `scale_curated`, `_driver_scaling` | `plan.estimate` quotes the observed figure ahead of the curated one, and blends it toward the curated figure below three runs. A `cost` entry is measured at the workflow's variable defaults; a run moving `num_inference_steps`, `width`/`height` or `num_frames` (per list entry, summed) scales it in proportion (`scale_curated`, which `dw/server/deps.py` reuses for an inherited figure), basis `derived` with `scaled` naming each axis, times the list-length re-price, and that scaled figure is what a thin observed one blends toward (#866). | `tests/test_plan.py::TestObservedEstimate::test_history_beats_a_curated_figure`, `tests/test_plan.py::TestLowConfidenceObservedEstimate::test_a_single_run_blends_toward_the_curated_figure`, `tests/test_plan.py::TestDriverScaling::test_steps_canvas_and_frames_multiply`, `tests/test_plan.py::TestScalingAccuracy::test_within_thirty_percent` |
@@ -112,8 +114,8 @@ one to open.
112
114
  | Acceleration warnings | `dw/acceleration_warnings.py`: `acceleration_warnings`, `CACHE_MIN_USEFUL_STEPS`, `CUDA_ONLY_ATTENTION_BACKENDS` (the last entry of `WARNING_CHECKS`) | An acceleration setting that can't pay off (a `first_block`/`mag` cache under `CACHE_MIN_USEFUL_STEPS`, any `taylorseer` cache, `compile.fullgraph` with a cache, a cache on a pipeline class with no transformer or whose transformer lacks `enable_cache()`, a CUDA-only `attention_backend` on a non-CUDA device) is a warning and never a refusal, and an unresolvable value (steps, backend, device) leaves it silent. | `tests/test_validation.py::TestAccelerationWarnings::test_warnings_never_refuse`, `tests/test_validation.py::TestAccelerationWarnings::test_steps_that_resolve_to_nothing_are_silent`, `tests/test_validation.py::TestAccelerationWarnings::test_an_unknown_device_is_silent`, `tests/test_validation.py::TestAccelerationWarnings::test_an_unresolvable_backend_is_silent_on_mps` |
113
115
  | H3 sparse attention | `dw/sparse_attention.py`: `sparse_call`, `install_sparse`, `install_sparse_for_call`, `apply_sparse_settings`, `SparseH3AttnProcessor`; wired from `dw/pipeline_processors/components.py`: `configure_components` and `dw/pipeline_processors/pipeline.py`: `apply_runtime_settings` | Whether a pipeline call runs sparse is decided once per call, all or nothing (the call's first kernel invocation included); it never changes diffusers' process-wide backend and never reaches `AttentionBackendName`; it installs by a processor swap plus forward hooks, never a `forward` wrapper; and `sparse_tau` is a runtime setting, not part of the weights identity (#931). | `tests/test_sparse_attention_processor.py`, `tests/test_sparse_attention_wiring.py`, `tests/test_sparse_attention_tiles.py`, `tests/test_sparse_attention_backends.py` |
114
116
  | H3 adapter partition | `dw/adapter_compatibility.py`; the server's index is `dw/server/deps.py` `lora_index` | The LoRA catalog decides first, on the server only: a `proven` entry's `workflow` refuses a step in the other partition, a `trial`/`rejected` entry's only warns. A file no entry places falls to its name: an FL2VA LoRA on a reference step is refused, and one whose name says neither `ref2v` nor `fl2v` is warned. | `tests/test_h3_adapters.py::TestWhatIsRefused::test_a_keyframe_adapter_on_the_reference_path`, `tests/test_h3_adapters.py::TestWhatIsRefused::test_an_unrecognised_name_is_a_warning_not_a_refusal`, `tests/test_h3_adapters.py::TestTheCatalogDecidesFirst::test_a_proven_entry_refuses_the_other_partition`, `tests/test_h3_adapters.py::TestTheCatalogDecidesFirst::test_a_weaker_entry_only_warns`, `tests/test_server_loras.py::TestTheCatalogPlacesAnAdapter::test_a_trial_entry_warns_and_promoting_it_refuses` |
115
- | H3 audio hold, refine, tiled refine and guide layout | Six modules, imported one way: `dw/pipeline_processors/h3_rules.py` holds the names and rules, torch- and diffusers-free (`refine_problems`, the per-argument refine rules, `refine_tiles` among them, asked before validation and before the call; `tile_plan`, the tile layout on the 32 px grid, shared by validate and the run; `not_h3`, the step rule; `snap_guide_length`, `guide_frame_problem`, `guide_chain_problems`, `guide_end_problem`; `CHAIN_CONTINUITY_MODES`; the chunk constants), `dw/pipeline_processors/h3_hold.py` puts the hold and refine blocks in (`insert_audio_hold`, `core_denoise_sequences`, `refines`; `HELD_LATENTS_OUTPUT` and `encoded_hold_audio`, the hold block's encode handed back to it), and `dw/pipeline_processors/h3_guides.py` the guide layout (`LAYOUT_ANCHORS`, `insert_guides`), which imports `h3_hold` and never the reverse; the blocks themselves, and the arithmetic they run, are `dw/pipeline_processors/h3_hold_steps.py` (`encode_audio_span`, `refine_sigmas`) and `dw/pipeline_processors/h3_guide_steps.py` (`splice_guide_rows`), which import diffusers when they load, so the two owners import them only inside `blocks()` and `guide_blocks()` (#790), and `h3_guide_steps` imports `h3_hold_steps` and never the reverse (`_with_guides` in `dw/pipeline_processors/pipeline.py` adds its blocks for a `guides` call), `dw/guides.py`: the `guides` validation check and the chain `continuity: "guide"` check, `guide_chain_errors`, which asks the `guides` check's own step rule (`_takes_guides_problem`, built on `h3_rules.not_h3` and `REFERENCE_WORKFLOWS`) and reads the mode names from `h3_rules.CHAIN_CONTINUITY_MODES`, the names `chain.py`'s `CONTINUITY_MODES` is zipped against (both registered in `dw/validation.py`; a `previous_result:` guide is checked at run time), `dw/pipeline_processors/h3_tiles.py`: the tiled refine (the tile loop, the latent-space feather blend, the per-tile crop of one whole-canvas noise draw, the decode-free graph variant, and the one spatially tiled decode), which imports `h3_rules`, `h3_hold` and `media_types` (for `FrameList`; and `events`, `progress`) and is imported by `pipeline.py` and, lazily, `components.py` (which attaches the variant at load, behind `h3_hold.core_denoise_sequences`), never by `h3_rules` or `h3_hold`, `dw/hold_audio.py`: `hold_audio_errors`, `refine_strength_errors` | The one place dw modifies a diffusers modular pipeline's block graph: three blocks go in, before `set_timesteps`, `denoise` and `after_denoise`, in every H3 core-denoise sequence (the whole graph and the `workflow=`-pruned flat graph), and they are no-ops without `hold_audio` / `refine_strength`. The tiled refine adds a second graph built at load beside them (`h3_tiles.decode_free_blocks`: the decode and text-encoder blocks dropped, every kept block the graph's own instance, so hold and refine stay in) and swaps it into `pipeline._blocks` only for the duration of the one text-encode call and the tile calls (`swapped_blocks`, restored on failure). Every tile runs the hold block, but the track is encoded once per refine: the first tile is asked for the block's encode (`HELD_LATENTS_OUTPUT`) and every later tile's `hold_audio` carries it (`encoded_hold_audio`, an `EncodedAudioReference`), which the block writes in place of running the audio VAE. A `hold_audio` path is opened only after `locations.validate_media_path` against the step's workflow directory. `dw/introspection.py` builds the same graph without weights, hold included, so `get_pipeline_signature` lists a modular pipeline's block inputs. The copies of diffusers behaviour are pinned to the installed diffusers: `shifted_sigma_grid` (the spacing `refine_sigmas` rests on) to stock `set_timesteps`, `GUIDE_FRAMES_PER_CHUNK`/`GUIDE_LATENTS_PER_CHUNK` to the H3 video VAE's `clip_length` and latents per clip, and every name in `LAYOUT_ANCHORS` (`_fill_audio_positions` among them) to `before_denoise`. | `tests/test_h3_hold_audio.py::TestAnchors::test_inserted_next_to_the_anchors_in_every_shape`, `tests/test_h3_hold_audio.py::TestHoldAudioLocation::test_a_path_outside_the_roots_is_refused_at_the_call`, `tests/test_h3_hold_audio.py::TestRefusals::test_a_non_h3_step_is_refused`, `tests/test_h3_hold_audio.py::TestSignature::test_the_h3_signature_shows_hold_audio`, `tests/test_h3_refine.py::TestAnchors::test_inserted_before_denoise_in_every_shape`, `tests/test_h3_tiles.py::TestDecodeFree::test_variant_has_no_decode_and_shares_blocks`, `tests/test_h3_tiles.py::TestTileLoop::test_blocks_are_restored_when_a_tile_fails`, `tests/test_h3_tiles.py::TestTileLoop::test_the_track_is_encoded_by_one_tile_and_handed_to_the_rest`, `tests/test_h3_hold_audio.py::TestHoldBlock::test_a_carried_encode_is_written_without_encoding_again`, `tests/test_h3_tiles.py`, `tests/test_h3_rules.py` (`tile_plan` and the `refine_tiles` rules), `tests/test_h3_refine.py::TestSigmaGridDrift::test_the_full_grid_is_stock_set_timesteps`, `tests/test_h3_guides.py::TestChunkDrift::test_frames_per_chunk_is_the_vae_clip_length`, `tests/test_h3_guides.py::TestChunkDrift::test_latents_per_chunk_is_the_vae_tokens_per_clip`, `tests/test_h3_guides.py::TestAnchors::test_installed_diffusers_has_every_anchor`, `tests/test_guide_chain_validation.py::TestRefused::test_the_step_rule_is_the_guides_rule`, `tests/test_guide_chain_validation.py::TestRefused::test_every_run_mode_is_known_to_validate`, `tests/test_h3_rules.py::test_h3_rules_imports_neither_torch_nor_diffusers`, `tests/test_h3_rules.py::test_the_block_owners_import_no_diffusers` |
116
- | IC-LoRA reference scale | `workflows/templates/ltx2/` | The three conditioning templates run at `reference_downscale_factor: 1`, and the two upscalers at 2. | `tests/test_ltx2_ic_loras.py::TestEachTemplateMatchesItsCard::test_the_reference_is_encoded_at_the_output_resolution`, `tests/test_ltx2_ic_loras.py::TestTheGenerativeUpscaleMatchesTheSameCard::test_it_loads_the_upscaler_at_factor_two` |
117
+ | H3 audio hold, refine, tiled refine, guide layout and regional edit | Nine modules, imported one way: `dw/pipeline_processors/h3_rules.py` holds the names and rules, torch- and diffusers-free (`refine_problems`, the per-argument refine rules, `refine_tiles` and the explicit `refine_sigmas` schedule among them, asked before validation and before the call; `tile_plan`, the tile layout on the 32 px grid, shared by validate and the run; `not_h3`, the step rule; `snap_guide_length`, `guide_frame_problem`, `guide_chain_problems`, `guide_end_problem`; `CHAIN_CONTINUITY_MODES`; the chunk constants; and the regional-edit rules `mask_problems`, `media_problems` and `edits_region`, the argument rules shared by validate and `_with_mask`; `media_problems` is asked by validate too, on the files that resolve then, and refuses a `source_video` off the `17n + 5` grid, which the pipeline would otherwise snap up over a padded source), `dw/pipeline_processors/h3_mask_cells.py` holds the mask-to-rows arithmetic (`binarized`, `regenerate_cells`, `keep_rows`), which `h3_mask.py` re-exports and `h3_mask_steps.py` reads from there so the blocks never import their importer, `dw/pipeline_processors/h3_hold.py` puts the hold and refine blocks in (`insert_audio_hold`, `core_denoise_sequences`, `refines`; `HELD_LATENTS_OUTPUT` and `encoded_hold_audio`, the hold block's encode handed back to it), and `dw/pipeline_processors/h3_guides.py` the guide layout (`LAYOUT_ANCHORS`, `insert_guides`), which imports `h3_hold` and never the reverse, and `dw/pipeline_processors/h3_mask.py` the regional edit (`insert_mask_blocks`, `edits_regions`, and the mask-to-rows arithmetic `binarized`, `regenerate_cells` and `keep_rows`, on Pillow's L conversion, torch's adaptive max pool and scipy's dilation, each imported where it runs), which imports `h3_hold` and never the reverse; the blocks themselves, and the arithmetic they run, are `dw/pipeline_processors/h3_hold_steps.py` (`encode_audio_span`, `refine_sigmas`, and `explicit_sigmas`, a step's `refine_sigmas` list run verbatim in place of the shift grid) `dw/pipeline_processors/h3_guide_steps.py` (`splice_guide_rows`) and `dw/pipeline_processors/h3_mask_steps.py` (the source-latents and mask-blend blocks), which import diffusers when they load, so the three owners import them only inside `blocks()`, `guide_blocks()` and `h3_mask.blocks()` (#790), and `h3_guide_steps` imports `h3_hold_steps` and never the reverse (`_with_guides` in `dw/pipeline_processors/pipeline.py` adds its blocks for a `guides` call, and `_with_mask` checks a regional edit's arguments and media and builds the regenerate mask for a `source_video` call), `dw/guides.py`: the `guides` validation check and the chain `continuity: "guide"` check, `guide_chain_errors`, which asks the `guides` check's own step rule (`_takes_guides_problem`, built on `h3_rules.not_h3` and `REFERENCE_WORKFLOWS`) and reads the mode names from `h3_rules.CHAIN_CONTINUITY_MODES`, the names `chain.py`'s `CONTINUITY_MODES` is zipped against (both registered in `dw/validation.py`; a `previous_result:` guide is checked at run time), `dw/pipeline_processors/h3_tiles.py`: the tiled refine (the tile loop, the latent-space feather blend, the per-tile crop of one whole-canvas noise draw, the decode-free graph variant, and the one spatially tiled decode), which imports `h3_rules`, `h3_hold` and `media_types` (for `FrameList`; and `events`, `progress`) and is imported by `pipeline.py` and, lazily, `components.py` (which attaches the variant at load, behind `h3_hold.core_denoise_sequences`, and calls `insert_mask_blocks` at load), never by `h3_rules` or `h3_hold`, `dw/hold_audio.py`: `hold_audio_errors` (a video is held by its soundtrack), `refine_strength_errors`, `mask_errors` (Check `regional_edit`, which probes the source and mask through `ValidationContext.probe` the way `dw/guides.py` probes guide videos) | The one place dw modifies a diffusers modular pipeline's block graph: three blocks go in, before `set_timesteps`, `denoise` and `after_denoise`, in every H3 core-denoise sequence (the whole graph and the `workflow=`-pruned flat graph), and two more for a regional edit: the source block before `set_timesteps` and the blend block inside the `denoise` loop after `update`. All are no-ops without their arguments (`hold_audio` / `refine_strength`, `source_video`). The tiled refine adds a second graph built at load beside them (`h3_tiles.decode_free_blocks`: the decode and text-encoder blocks dropped, every kept block the graph's own instance, so hold and refine stay in) and swaps it into `pipeline._blocks` only for the duration of the one text-encode call and the tile calls (`swapped_blocks`, restored on failure). Every tile runs the hold block, but the track is encoded once per refine: the first tile is asked for the block's encode (`HELD_LATENTS_OUTPUT`) and every later tile's `hold_audio` carries it (`encoded_hold_audio`, an `EncodedAudioReference`), which the block writes in place of running the audio VAE. A `hold_audio` path is opened only after `locations.validate_media_path` against the step's workflow directory. `dw/introspection.py` builds the same graph without weights, hold included, so `get_pipeline_signature` lists a modular pipeline's block inputs. The copies of diffusers behaviour are pinned to the installed diffusers: `shifted_sigma_grid` (the spacing `refine_sigmas` rests on) to stock `set_timesteps`, `GUIDE_FRAMES_PER_CHUNK`/`GUIDE_LATENTS_PER_CHUNK` to the H3 video VAE's `clip_length` and latents per clip, and every name in `LAYOUT_ANCHORS` (`_fill_audio_positions` among them) to `before_denoise`. | `tests/test_h3_hold_audio.py::TestAnchors::test_inserted_next_to_the_anchors_in_every_shape`, `tests/test_h3_hold_audio.py::TestHoldAudioLocation::test_a_path_outside_the_roots_is_refused_at_the_call`, `tests/test_h3_hold_audio.py::TestRefusals::test_a_non_h3_step_is_refused`, `tests/test_h3_hold_audio.py::TestSignature::test_the_h3_signature_shows_hold_audio`, `tests/test_h3_refine.py::TestAnchors::test_inserted_before_denoise_in_every_shape`, `tests/test_h3_tiles.py::TestDecodeFree::test_variant_has_no_decode_and_shares_blocks`, `tests/test_h3_tiles.py::TestTileLoop::test_blocks_are_restored_when_a_tile_fails`, `tests/test_h3_tiles.py::TestTileLoop::test_the_track_is_encoded_by_one_tile_and_handed_to_the_rest`, `tests/test_h3_hold_audio.py::TestHoldBlock::test_a_carried_encode_is_written_without_encoding_again`, `tests/test_h3_tiles.py`, `tests/test_h3_rules.py` (`tile_plan` and the `refine_tiles` rules), `tests/test_h3_mask.py`, `tests/test_h3_refine.py::TestSigmaGridDrift::test_the_full_grid_is_stock_set_timesteps`, `tests/test_h3_refine.py::TestSigmaListOneOwner::test_the_runtime_message_is_the_owners`, `tests/test_h3_refine.py::TestSigmaListSchedule::test_the_block_runs_the_list_unshifted`, `tests/test_h3_guides.py::TestChunkDrift::test_frames_per_chunk_is_the_vae_clip_length`, `tests/test_h3_guides.py::TestChunkDrift::test_latents_per_chunk_is_the_vae_tokens_per_clip`, `tests/test_h3_guides.py::TestAnchors::test_installed_diffusers_has_every_anchor`, `tests/test_guide_chain_validation.py::TestRefused::test_the_step_rule_is_the_guides_rule`, `tests/test_guide_chain_validation.py::TestRefused::test_every_run_mode_is_known_to_validate`, `tests/test_h3_rules.py::test_h3_rules_imports_neither_torch_nor_diffusers`, `tests/test_h3_rules.py::test_the_block_owners_import_no_diffusers` |
118
+ | IC-LoRA reference scale | `workflows/templates/ltx2/` | The five conditioning templates run at `reference_downscale_factor: 1`, and the two upscalers at 2. | `tests/test_ltx2_ic_loras.py::TestEachTemplateMatchesItsCard::test_the_reference_is_encoded_at_the_output_resolution`, `tests/test_ltx2_ic_loras.py::TestTheGenerativeUpscaleMatchesTheSameCard::test_it_loads_the_upscaler_at_factor_two` |
117
119
  | IC-LoRA numbers | `workflows/templates/ltx2/` | Every number in the IC-LoRA templates comes from the vendor's model card. | `tests/test_ltx2_ic_loras.py::TestEachTemplateMatchesItsCard::test_the_strength_is_the_cards_default`, `tests/test_ltx2_ic_loras.py::TestEachTemplateMatchesItsCard::test_the_defaults_are_the_trained_bucket` |
118
120
  | IC-LoRA prompt genre | `prompts/ltx2/` | A stored prompt tagged `ic-lora` is checked against its trained caption form, not against the T2V paragraph rule. | `tests/test_ltx_prompt_library.py::test_an_ic_lora_prompt_is_in_its_trained_form` |
119
121
 
@@ -135,13 +137,14 @@ one to open.
135
137
 
136
138
  | Concept | Owner | Rule | Enforced by |
137
139
  | --- | --- | --- | --- |
138
- | Opening media | `dw/media.py` | This is the only module that calls `av.open`. It imports no torch and no step types. | `tests/test_media_layering.py::test_av_open_appears_only_in_media`, `tests/test_media_layering.py::test_media_imports_no_step_types` (no torch: —) |
140
+ | Opening media | `dw/media.py`, `dw/media_readers.py` (the frame readers, re-exported by `dw/media.py`, which imports from it and never the reverse) | These are the only modules that call `av.open`. They import no torch and no step types. | `tests/test_media_layering.py::test_av_open_appears_only_in_media`, `tests/test_media_layering.py::test_media_imports_no_step_types` (no torch: —) |
139
141
  | Frame moments and crops | `dw/media_frames.py`: `moment_index`, `parse_crop` | One `at` grammar ("frame:N", or seconds at the clip's fps; negative counts back from the end for `get_output_frames` and is refused by `compare_outputs`) and one `[x, y, width, height]` crop parse serve `get_output_frames` and `compare_outputs`. Only the bounds policy is the caller's: `get_output_frames` refuses a moment past the end and clamps a crop (`_moment_to_index`, `resolve_crop_box`); `compare_outputs` blanks a past-end cell and refuses a crop that doesn't fit an output. | `tests/test_media_compare.py::test_resolve_moments_refuses_what_get_output_frames_refuses`, `tests/test_media_compare.py::test_crop_box_refuses_a_malformed_box_as_resolve_crop_box_does` |
140
142
  | Output comparison | `dw/media_compare.py`: `compare`, `psnr`, `ssim`, `mean_abs_diff`, `check_request`, `crop_box` | Metrics always compare the same pixels: one shared crop is the measured region, and per-output crops are display only, leaving metrics on the full frame. An output whose size differs from the baseline's, or a moment past its end, gets null metrics with a reason; nothing is resized to force a number. SSIM is on Rec. 601 luma (SSIM's convention, not `image_ops.luma`). It runs in the server process and decodes through `dw/media.py` and `open_bounded`. | `tests/test_compare_route.py::test_a_shared_crop_is_the_region_measured`, `tests/test_compare_route.py::test_per_output_crops_are_display_only`, `tests/test_compare_route.py::test_a_size_mismatch_gets_no_numbers_and_says_why`, `tests/test_compare_route.py::test_a_moment_past_the_shorter_clip_is_a_blank_cell` |
141
143
  | Signal processing | `dw/dsp.py` | It measures and transforms waveforms, decides nothing, and imports nothing from `dw`. | `tests/test_media_layering.py::test_dsp_imports_nothing_from_dw` |
142
144
  | Assessment probes | `dw/tasks/assess.py`, `dw/assessment_rules.py` | Exactly three registered commands are assessment probes. Each measures a finished file, and every rule names a real probe field. | `tests/test_assessment_rules.py::TestRuleProbesAreRealCommands::test_assessment_is_exactly_the_three_probes`, `tests/test_assessment_rules.py::TestRuleProbesAreRealCommands::test_every_rule_names_a_registered_json_command` |
143
- | Script check | `dw/tasks/script_check.py`: `check`; `dw/tasks/script_take.py`: `guard_words`, `word_level`, `shot_spans`; `dw/script_lines.py`: `parse_lines`, `parse_shots`, `shot_names_error` | `check_script` aligns a take's heard words to its expected lines and guards out words heard over silence and repetition loops (Whisper's hallucination over music). It builds its findings with `assessment_rules.finding()` and reads the guard's floor and window (`DEAD_AIR_FLOOR_DBFS`, `DEAD_AIR_WINDOW`) rather than copying them; the loudest-window measure is `dsp.loudest_window_dbfs` (`script_take.word_level` wraps it; the guard, the transcription levelling and the shot placement are `dw/tasks/script_take.py`, which `script_check` reads one way - nothing there reads the rule tables), which `transcribe_audio`'s `suspect: "silent"` mark reads with the same floor and window; the repetition-loop detector (`script_lines.looped_texts`, `REPEAT_RUN_MIN`, `REPEAT_MAX_PERIOD`) lives in `dw/script_lines.py` and backs both `check_script`'s `repetition` discard and `transcribe_audio`'s `suspect: "repetition"`, and `script_lines.suspect_runs`/`SUSPECT_LEFT_OUT` are what `plan_cuts` groups and leaves out suspect chunks by - so neither task imports the other. It is not an assessment probe and adds nothing to `RULES`. Its literal `lines` is refused at validation through `task_problems` (`script_lines_errors`), which calls the same `parse_lines` the task runs, and a literal `shots` through the same `parse_shots` and `shot_names_error`; the parsers live in `dw/script_lines.py`, not the task, so that `task_problems` reaches them without importing `script_check` (the `import_cycles` ratchet in `scripts/arch_metrics.py`). A line's `shot` may be the short `@name` of the one recorded shot that carries it (`script_lines.matching_shot_names`, `with_full_shot_names`, shared by the task and the literal-`shots` check); which member key a recorded name carries comes from `references.member_keys`, beside `MEMBER_SEPARATOR` and `for_each.member_name`, never a re-derived pattern: a key ends at the first character outside `references.VARIABLE_NAME_CHARACTERS`, the set `security.validate_variable_name` (which checks a for_each entry's name) builds its pattern from. With `audio` an `output:`/`asset:`/path whose run manifest records shots, `dw/shot_span_preflight.py: script_shot_name_errors` (the `script_shot_names` error check) runs `shot_names_error` at validation, reading the map through `runs.shots_beside`. Its shot map comes from `assess.resolve_shots`, the one the probes use, never a copy; it places each shot on the soundtrack with `assess.sample_span`, decides repeated shot names with `shots.duplicate_shot_names`, and asks `locations.is_http_url` whether the take is a URL. | `tests/test_script_check.py::TestRegistration::test_registered_as_json_command_without_assessment_flag`, `tests/test_script_check.py::TestEmptyLines::test_words_only_over_silence_are_discarded_not_found`, `tests/test_script_check.py::TestLinesErrors::test_literal_with_a_colon_is_not_a_reference`, `tests/test_script_check.py::TestShotValidation::test_a_short_member_name_matches_the_one_shot_carrying_it`, `tests/test_script_check.py::TestShotValidation::test_a_valid_variable_name_comes_back_whole_as_a_member_key`, `tests/test_shot_span_preflight.py::TestScriptShotNames::test_a_wrong_shot_name_is_an_error_at_validate_time` |
145
+ | Script check | `dw/tasks/script_check.py`: `check`; `dw/tasks/script_findings.py`: the rule constants and the finding builders `check` calls (imported one way, re-exported by `script_check`); `dw/tasks/script_take.py`: `guard_words`, `word_level`, `shot_spans`; `dw/script_lines.py`: `parse_lines`, `parse_shots`, `shot_names_error` | `check_script` aligns a take's heard words to its expected lines and guards out words heard over silence and repetition loops (Whisper's hallucination over music). It builds its findings with `assessment_rules.finding()` and reads the guard's floor and window (`DEAD_AIR_FLOOR_DBFS`, `DEAD_AIR_WINDOW`) rather than copying them; the loudest-window measure is `dsp.loudest_window_dbfs` and the looped-bed self-correlation `dsp.repeat_correlation` (`script_findings.is_looped_bed` only decides on it) (`script_take.word_level` wraps it; the guard, the transcription levelling, the floor-gated `audible_runs` and the shot placement (with `clamp_to_shot`, a line's timing kept inside its shot) are `dw/tasks/script_take.py`, which `script_check` reads one way - nothing there reads the rule tables), which `transcribe_audio`'s `suspect: "silent"` mark reads with the same floor and window; the repetition-loop detector (`script_lines.looped_texts`, `REPEAT_RUN_MIN`, `REPEAT_MAX_PERIOD`) lives in `dw/script_lines.py` and backs both `check_script`'s `repetition` discard and `transcribe_audio`'s `suspect: "repetition"`, and `script_lines.suspect_runs`/`SUSPECT_LEFT_OUT` are what `plan_cuts` groups and leaves out suspect chunks by - so neither task imports the other. It is not an assessment probe and adds nothing to `RULES`. Its literal `lines` is refused at validation through `task_problems` (`script_lines_errors`), which calls the same `parse_lines` the task runs, and a literal `shots` through the same `parse_shots` and `shot_names_error`; the parsers live in `dw/script_lines.py`, not the task, so that `task_problems` reaches them without importing `script_check` (the `import_cycles` ratchet in `scripts/arch_metrics.py`). A line's `shot` may be the short `@name` of the one recorded shot that carries it (`script_lines.matching_shot_names`, `with_full_shot_names`, shared by the task and the literal-`shots` check); which member key a recorded name carries comes from `references.member_keys`, beside `MEMBER_SEPARATOR` and `for_each.member_name`, never a re-derived pattern: a key ends at the first character outside `references.VARIABLE_NAME_CHARACTERS`, the set `security.validate_variable_name` (which checks a for_each entry's name) builds its pattern from. With `audio` an `output:`/`asset:`/path whose run manifest records shots, `dw/shot_span_preflight.py: script_shot_name_errors` (the `script_shot_names` error check) runs `shot_names_error` at validation, reading the map through `runs.shots_beside`. Its shot map comes from `assess.resolve_shots`, the one the probes use, never a copy; it places each shot on the soundtrack with `assess.sample_span`, decides repeated shot names with `shots.duplicate_shot_names`, and asks `locations.is_http_url` whether the take is a URL. | `tests/test_script_check.py::TestRegistration::test_registered_as_json_command_without_assessment_flag`, `tests/test_script_check.py::TestEmptyLines::test_words_only_over_silence_are_discarded_not_found`, `tests/test_script_check.py::TestLinesErrors::test_literal_with_a_colon_is_not_a_reference`, `tests/test_script_check.py::TestShotValidation::test_a_short_member_name_matches_the_one_shot_carrying_it`, `tests/test_script_check.py::TestShotValidation::test_a_valid_variable_name_comes_back_whole_as_a_member_key`, `tests/test_shot_span_preflight.py::TestScriptShotNames::test_a_wrong_shot_name_is_an_error_at_validate_time` |
144
146
  | Audio sync against a source slice | `dw/tasks/measure_sync.py`: `measure_sync`; `dw/dsp.py`: `envelope_lag` | `measure_sync` cross-correlates the onset envelopes of a shot's audio and its source slice and answers the lag and a 0-1 confidence. A positive lag means the audio is LATE (its events fall after the reference's), negative early; `lag_seconds` is None for a silent or flat track. It builds its findings (`sync_unmeasurable`, `sync_low_confidence`, `audio_out_of_sync`) with `assessment_rules.finding()` over module-local rule dicts and adds nothing to `RULES`; it reads the silence floor from `beats.SILENT_DBFS`. `envelope_lag` imports nothing from `dw`. | `tests/test_measure_sync.py::TestLag::test_late_audio_is_a_positive_lag`, `tests/test_measure_sync.py::TestLag::test_early_audio_is_a_negative_lag`, `tests/test_measure_sync.py::TestUnmeasurable::test_a_silent_reference_has_no_lag` |
147
+ | Sung phrases from voiced energy | `dw/tasks/phrases.py`: `analyze_phrases`, `voiced_power`, `voiced_runs`; `dw/task_problems.py`: `phrases_problems`, `phrases_errors` | `analyze_phrases` times a song's sung phrases with no model: a stereo file's centre-weighted band power (max(0, P_mid - P_side), 250-3500 Hz, 20 ms frames) or, for mono, `centre: false` or identical channels, the downmix's band power (`method` `band`). The voiced floor is `voice_attribution.voiced_floor_dbfs`, the rule `attribute_voices` uses, unless `floor_db` is given. It answers a dict - `{phrases, duration_seconds, method, warnings}` - so a step saves one JSON artifact. Its ranges are the registration's domains; `phrases_problems` (a real boolean `centre`) runs at validate and at run time. | `tests/test_analyze_phrases.py::TestCentre::test_centred_bursts_under_hard_panned_noise_are_found`, `tests/test_analyze_phrases.py::TestCentre::test_bursts_panned_hard_to_one_side_are_not_centre`, `tests/test_analyze_phrases.py::TestRefusals::test_validate_refuses_a_missing_audio_and_a_negative_gap` |
145
148
 
146
149
  ## Security and architecture guardrails
147
150