diffusers-workflow 0.15.0__tar.gz → 0.16.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 (665) hide show
  1. {diffusers_workflow-0.15.0/diffusers_workflow.egg-info → diffusers_workflow-0.16.0}/PKG-INFO +1 -1
  2. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0/diffusers_workflow.egg-info}/PKG-INFO +1 -1
  3. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/diffusers_workflow.egg-info/SOURCES.txt +37 -22
  4. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/acceleration_warnings.py +1 -1
  5. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/adapter_compatibility.py +16 -1
  6. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/argument_media.py +2 -2
  7. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/devices.py +21 -4
  8. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/ARCHITECTURE.md +13 -7
  9. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/DEPENDENCIES.md +1 -1
  10. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/MCP.md +7 -5
  11. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/RELEASING.md +137 -0
  12. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/SECURITY.md +7 -1
  13. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/SECURITY_QUICKREF.md +1 -0
  14. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/SERVER.md +26 -7
  15. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/TASKS.md +141 -17
  16. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/WORKFLOW_GUIDE.md +427 -13
  17. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/hold_audio.py +52 -13
  18. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/introspection.py +4 -1
  19. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/locations.py +46 -51
  20. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/media.py +27 -6
  21. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/media_types.py +53 -0
  22. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/outbound.py +10 -5
  23. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/output_extraction.py +50 -2
  24. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/components.py +11 -145
  25. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/h3_hold.py +18 -0
  26. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/h3_hold_steps.py +83 -13
  27. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/h3_rules.py +220 -5
  28. diffusers_workflow-0.16.0/dw/pipeline_processors/h3_tiles.py +366 -0
  29. diffusers_workflow-0.16.0/dw/pipeline_processors/mag_calibration.py +158 -0
  30. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/pipeline.py +17 -3
  31. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/progress.py +22 -1
  32. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/plan.py +28 -205
  33. diffusers_workflow-0.16.0/dw/plan_downloads.py +346 -0
  34. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/roles.py +17 -7
  35. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/script_lines.py +35 -6
  36. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/security.py +52 -0
  37. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/serve.py +8 -2
  38. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/admission.py +40 -25
  39. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/api_models.py +11 -0
  40. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/deps.py +13 -1
  41. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/job_history.py +127 -110
  42. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/job_results.py +6 -0
  43. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/jobs.py +15 -1
  44. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/observed_cost.py +13 -3
  45. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/outputs.py +48 -6
  46. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/routes/assets.py +0 -7
  47. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/routes/gallery.py +16 -36
  48. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/routes/jobs.py +38 -3
  49. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/routes/media.py +9 -11
  50. diffusers_workflow-0.15.0/dw/server/ui/assets/cssMode-D_BuRO9Y.js → diffusers_workflow-0.16.0/dw/server/ui/assets/cssMode-Cx99RWkL.js +1 -1
  51. diffusers_workflow-0.15.0/dw/server/ui/assets/editor.api-B6pi6BSE.js → diffusers_workflow-0.16.0/dw/server/ui/assets/editor.api-jKhYFhrF.js +1 -1
  52. diffusers_workflow-0.15.0/dw/server/ui/assets/freemarker2-mPiw3NV_.js → diffusers_workflow-0.16.0/dw/server/ui/assets/freemarker2-Cr_kdwwJ.js +1 -1
  53. diffusers_workflow-0.15.0/dw/server/ui/assets/handlebars-BfGb596Y.js → diffusers_workflow-0.16.0/dw/server/ui/assets/handlebars-CnbOycVf.js +1 -1
  54. diffusers_workflow-0.15.0/dw/server/ui/assets/html-xXIqw-JZ.js → diffusers_workflow-0.16.0/dw/server/ui/assets/html-vCIOVoPc.js +1 -1
  55. diffusers_workflow-0.15.0/dw/server/ui/assets/htmlMode-B3FC_H4q.js → diffusers_workflow-0.16.0/dw/server/ui/assets/htmlMode-B5ESZlHK.js +1 -1
  56. diffusers_workflow-0.16.0/dw/server/ui/assets/index-Bm_jBlG4.css +1 -0
  57. diffusers_workflow-0.16.0/dw/server/ui/assets/index-DIXj1Pp3.js +65 -0
  58. diffusers_workflow-0.15.0/dw/server/ui/assets/javascript-B-FFcgST.js → diffusers_workflow-0.16.0/dw/server/ui/assets/javascript-DpV2UaWD.js +1 -1
  59. diffusers_workflow-0.15.0/dw/server/ui/assets/jsonMode-BELbxUQD.js → diffusers_workflow-0.16.0/dw/server/ui/assets/jsonMode-DaGlZZy1.js +1 -1
  60. diffusers_workflow-0.15.0/dw/server/ui/assets/liquid-CxXhb7_e.js → diffusers_workflow-0.16.0/dw/server/ui/assets/liquid-Ds835QKV.js +1 -1
  61. diffusers_workflow-0.15.0/dw/server/ui/assets/lspLanguageFeatures-sXyBqSzn.js → diffusers_workflow-0.16.0/dw/server/ui/assets/lspLanguageFeatures-Cd9OxrIO.js +1 -1
  62. diffusers_workflow-0.15.0/dw/server/ui/assets/mdx-4jPGQ4yb.js → diffusers_workflow-0.16.0/dw/server/ui/assets/mdx-BozOHFIi.js +1 -1
  63. diffusers_workflow-0.15.0/dw/server/ui/assets/monaco-ByFdQnrs.js → diffusers_workflow-0.16.0/dw/server/ui/assets/monaco-673w9Wwq.js +4 -4
  64. diffusers_workflow-0.15.0/dw/server/ui/assets/python-D3CL9Y6O.js → diffusers_workflow-0.16.0/dw/server/ui/assets/python-D_HjE-WC.js +1 -1
  65. diffusers_workflow-0.15.0/dw/server/ui/assets/razor-F_hjmtqk.js → diffusers_workflow-0.16.0/dw/server/ui/assets/razor-DjEZAQZw.js +1 -1
  66. diffusers_workflow-0.15.0/dw/server/ui/assets/tsMode-BiyDvHYY.js → diffusers_workflow-0.16.0/dw/server/ui/assets/tsMode-B3g7-HAd.js +1 -1
  67. diffusers_workflow-0.15.0/dw/server/ui/assets/typescript-DBE1Uz0U.js → diffusers_workflow-0.16.0/dw/server/ui/assets/typescript-Bq3yLFs6.js +1 -1
  68. diffusers_workflow-0.15.0/dw/server/ui/assets/workers-Ci7sZ35J.js → diffusers_workflow-0.16.0/dw/server/ui/assets/workers-Jt2I7Jya.js +1 -1
  69. diffusers_workflow-0.15.0/dw/server/ui/assets/xml-Eqpmo6a1.js → diffusers_workflow-0.16.0/dw/server/ui/assets/xml-BD0Sm95a.js +1 -1
  70. diffusers_workflow-0.15.0/dw/server/ui/assets/yaml-BNP_JiwW.js → diffusers_workflow-0.16.0/dw/server/ui/assets/yaml-BSnko3ic.js +1 -1
  71. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/index.html +2 -2
  72. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/task_domains.py +6 -1
  73. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/task_problems.py +4 -3
  74. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/assess.py +174 -16
  75. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/audio_dynamics.py +112 -3
  76. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/audio_transcription.py +26 -3
  77. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/background_remover.py +12 -1
  78. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/depth_estimator.py +27 -2
  79. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/diffusion_upscale.py +18 -2
  80. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/face_track.py +18 -1
  81. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/h3_latent_upscale.py +93 -33
  82. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/image_to_text.py +1 -0
  83. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/image_utils.py +49 -9
  84. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/interpolate_frames.py +18 -2
  85. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/judge.py +1 -0
  86. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/model_handlers.py +96 -9
  87. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/pair_audio.py +17 -6
  88. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/registry.py +57 -0
  89. diffusers_workflow-0.16.0/dw/tasks/remove_object.py +201 -0
  90. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/restore_faces.py +39 -2
  91. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/script_check.py +424 -231
  92. diffusers_workflow-0.16.0/dw/tasks/script_take.py +223 -0
  93. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/segment.py +46 -9
  94. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/speech_generation.py +25 -2
  95. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/text_generation.py +37 -8
  96. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/upscale.py +19 -1
  97. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/video_handlers.py +1 -0
  98. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/video_utils.py +9 -28
  99. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/voice_attribution.py +119 -5
  100. diffusers_workflow-0.16.0/dw/tasks/weights.py +90 -0
  101. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/validation.py +11 -1
  102. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/vram_estimate.py +121 -7
  103. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/vram_inheritance.py +105 -16
  104. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/worker.py +7 -0
  105. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/worker_manager.py +13 -0
  106. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/worker_protocol.py +16 -0
  107. diffusers_workflow-0.16.0/dw/workflows/h3_context_ir.json +57 -0
  108. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/catalog.py +2 -2
  109. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/client.py +5 -1
  110. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/tools_catalog.py +1 -1
  111. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/pyproject.toml +1 -1
  112. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_admission.py +216 -1
  113. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_api_contract.py +7 -3
  114. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_audio_utils.py +68 -0
  115. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_cache_blocks.py +17 -17
  116. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_catalog_structure.py +11 -1
  117. diffusers_workflow-0.16.0/tests/test_chain_h3_native.py +210 -0
  118. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_forget_workspace_history.py +21 -9
  119. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_gallery_roles.py +77 -6
  120. diffusers_workflow-0.16.0/tests/test_guide_pointers.py +132 -0
  121. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_context_ir.py +14 -0
  122. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_hold_audio.py +43 -0
  123. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_latent_upscale.py +93 -9
  124. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_refine.py +214 -0
  125. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_rules.py +56 -0
  126. diffusers_workflow-0.16.0/tests/test_h3_tiles.py +411 -0
  127. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_upscaler_source.py +2 -1
  128. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_vram_ceiling.py +16 -0
  129. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_inherited_cost.py +57 -9
  130. diffusers_workflow-0.16.0/tests/test_job_history_parity.py +58 -0
  131. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_locations.py +82 -0
  132. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_lora_disable.py +12 -0
  133. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_client.py +15 -2
  134. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_server.py +20 -150
  135. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_modular_output_properties.py +45 -2
  136. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_modular_progress.py +26 -0
  137. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_notes_api.py +31 -0
  138. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_observed_cost.py +19 -0
  139. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_outbound.py +53 -2
  140. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_pipeline_components.py +71 -0
  141. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_plan.py +213 -34
  142. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_plugin_skills.py +12 -5
  143. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_reference_limits.py +6 -1
  144. diffusers_workflow-0.16.0/tests/test_remove_object.py +353 -0
  145. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_roles.py +20 -1
  146. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_script_check.py +297 -12
  147. diffusers_workflow-0.16.0/tests/test_seam_look.py +254 -0
  148. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_security_ssrf.py +8 -1
  149. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_segment.py +58 -2
  150. diffusers_workflow-0.16.0/tests/test_separate_stems.py +212 -0
  151. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_serve_main.py +47 -0
  152. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server.py +97 -23
  153. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_jobs.py +120 -5
  154. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_step_cache.py +2 -0
  155. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_task_domains.py +15 -0
  156. diffusers_workflow-0.16.0/tests/test_task_file_weights.py +340 -0
  157. diffusers_workflow-0.16.0/tests/test_task_weights.py +506 -0
  158. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_vram_estimate.py +106 -1
  159. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_vram_inheritance.py +114 -3
  160. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_worker_execute.py +33 -0
  161. diffusers_workflow-0.16.0/tests/test_zimage_vram.py +61 -0
  162. diffusers_workflow-0.15.0/dw/server/ui/assets/index-Civ6zDZP.js +0 -64
  163. diffusers_workflow-0.15.0/dw/server/ui/assets/index-PRSQwOeN.css +0 -1
  164. diffusers_workflow-0.15.0/dw/workflows/h3_context_ir.json +0 -57
  165. diffusers_workflow-0.15.0/tests/test_separate_stems.py +0 -105
  166. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/LICENSE +0 -0
  167. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/MANIFEST.in +0 -0
  168. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/README.md +0 -0
  169. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/diffusers_workflow.egg-info/dependency_links.txt +0 -0
  170. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/diffusers_workflow.egg-info/entry_points.txt +0 -0
  171. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/diffusers_workflow.egg-info/requires.txt +0 -0
  172. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/diffusers_workflow.egg-info/top_level.txt +0 -0
  173. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/__init__.py +0 -0
  174. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/argument_warnings.py +0 -0
  175. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/arguments.py +0 -0
  176. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/assessment_rules.py +0 -0
  177. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/assets.py +0 -0
  178. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/audio_qc.py +0 -0
  179. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/cache_blocks.json +0 -0
  180. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/cache_blocks.py +0 -0
  181. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/community_pipelines/pipeline_flux_rf_inversion.py +0 -0
  182. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/community_pipelines/pipeline_ltx2_refine.py +0 -0
  183. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/content_types.py +0 -0
  184. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/cost_scaling.py +0 -0
  185. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/disk_caches.py +0 -0
  186. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/dissolve_frame_errors.py +0 -0
  187. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/ACCELERATION.md +0 -0
  188. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/AGENT_LOOP.md +0 -0
  189. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/IP_ADAPTER.md +0 -0
  190. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/LORAS.md +0 -0
  191. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/PROMPT_WEIGHTING.md +0 -0
  192. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/QUANTIZATION.md +0 -0
  193. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/RECIPES_24GB.md +0 -0
  194. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/REMOTE.md +0 -0
  195. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/TESTING.md +0 -0
  196. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/WORKER_GUIDE.md +0 -0
  197. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/docs/WORKSPACES.md +0 -0
  198. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/download_watch.py +0 -0
  199. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/dsp.py +0 -0
  200. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/elision.py +0 -0
  201. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/events.py +0 -0
  202. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/for_each.py +0 -0
  203. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/guides.py +0 -0
  204. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/host_memory.py +0 -0
  205. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/host_memory_projection.py +0 -0
  206. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/hub_cache.py +0 -0
  207. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/kernel_availability.py +0 -0
  208. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/library.py +0 -0
  209. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/log_setup.py +0 -0
  210. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/lora_catalog.py +0 -0
  211. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/lora_catalog_schema.json +0 -0
  212. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/lora_hub.py +0 -0
  213. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/media_compare.py +0 -0
  214. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/media_frames.py +0 -0
  215. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/notes.py +0 -0
  216. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/path_redaction.py +0 -0
  217. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_ownership.py +0 -0
  218. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/adapters.py +0 -0
  219. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/chain.py +0 -0
  220. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/config_objects.py +0 -0
  221. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/h3_guide_steps.py +0 -0
  222. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/h3_guides.py +0 -0
  223. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/placement.py +0 -0
  224. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/remote.py +0 -0
  225. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/pipeline_processors/timing.py +0 -0
  226. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/previous_results.py +0 -0
  227. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/probe_paths.py +0 -0
  228. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/prompt_schema.json +0 -0
  229. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/prompt_weighting.py +0 -0
  230. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/prompts.py +0 -0
  231. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/quantized_cache.py +0 -0
  232. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/realize.py +0 -0
  233. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/reference_limits.py +0 -0
  234. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/reference_names.py +0 -0
  235. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/references.py +0 -0
  236. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/result.py +0 -0
  237. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/run.py +0 -0
  238. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/runs.py +0 -0
  239. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/scalar_result_validation.py +0 -0
  240. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/schema.py +0 -0
  241. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/__init__.py +0 -0
  242. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/api_models_base.py +0 -0
  243. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/api_models_library.py +0 -0
  244. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/app.py +0 -0
  245. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/assess.py +0 -0
  246. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/catalog.py +0 -0
  247. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/catalog_shape.py +0 -0
  248. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/dispatch.py +0 -0
  249. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/enhancers.py +0 -0
  250. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/exports.py +0 -0
  251. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/guides.py +0 -0
  252. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/host_ram_need.py +0 -0
  253. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/http_security.py +0 -0
  254. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/inline_media.py +0 -0
  255. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/job_record.py +0 -0
  256. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/mcp_mount.py +0 -0
  257. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/netinfo.py +0 -0
  258. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/pool.py +0 -0
  259. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/routes/__init__.py +0 -0
  260. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/routes/files.py +0 -0
  261. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/routes/library.py +0 -0
  262. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/routes/loras.py +0 -0
  263. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/routes/system.py +0 -0
  264. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/sysinfo.py +0 -0
  265. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/abap-08VXUWAP.js +0 -0
  266. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/apex-BWPQTe0t.js +0 -0
  267. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/azcli-Bc_sGQ0U.js +0 -0
  268. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/bat-i0X4ZdIN.js +0 -0
  269. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/bicep-B5-_aFwp.js +0 -0
  270. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/cameligo-DMUM7wLl.js +0 -0
  271. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/clojure-Cm7r79vr.js +0 -0
  272. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/codicon-DF1abBS2.ttf +0 -0
  273. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/coffee-Ba7i2nA0.js +0 -0
  274. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/cpp-C7h46wYY.js +0 -0
  275. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/csharp-BKxtCVv1.js +0 -0
  276. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/csp-bTuwJoIa.js +0 -0
  277. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/css-DIMkf-bt.js +0 -0
  278. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/css.worker-C6lDtRpF.js +0 -0
  279. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/cypher-CVaqCwHa.js +0 -0
  280. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/dart-onAF5SnQ.js +0 -0
  281. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/dockerfile-DZFCIeNp.js +0 -0
  282. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/ecl-D05T4iGw.js +0 -0
  283. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/editor-DjpsE8to.css +0 -0
  284. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/editor.worker-BmdWdrHZ.js +0 -0
  285. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/elixir-6RTg0lbw.js +0 -0
  286. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/flow9-C5_-GSwl.js +0 -0
  287. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/fsharp-C8Ef5oNN.js +0 -0
  288. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/go-C-y9NEjX.js +0 -0
  289. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/graphql-fmXr3nnJ.js +0 -0
  290. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/hcl-CpzslTdj.js +0 -0
  291. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/html.worker-C5yZDBHz.js +0 -0
  292. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/ini-sBoK_t0W.js +0 -0
  293. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/java-BEtHBSE6.js +0 -0
  294. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/json.worker-DdeUAmHa.js +0 -0
  295. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/julia-Bri6UV-V.js +0 -0
  296. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/kotlin-BOotOW0E.js +0 -0
  297. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/less-B9JPFI3C.js +0 -0
  298. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/lexon-CfSJPG6W.js +0 -0
  299. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/lua-CsQS60Ue.js +0 -0
  300. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/m3-D-oSqn_W.js +0 -0
  301. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/markdown-Cimd5fb3.js +0 -0
  302. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/mips-CIPQ_RoX.js +0 -0
  303. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/monaco-n7clI0si.css +0 -0
  304. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/msdax-DauUninz.js +0 -0
  305. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/mysql-SOo6toE5.js +0 -0
  306. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/objective-c-FvmIjYaQ.js +0 -0
  307. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/pascal-DrH0SRf2.js +0 -0
  308. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/pascaligo-D-ptJ9y-.js +0 -0
  309. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/perl-oz_6vUea.js +0 -0
  310. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/pgsql-DTj74zXo.js +0 -0
  311. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/php-nr791fC2.js +0 -0
  312. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/pla-CopQ2nXW.js +0 -0
  313. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/postiats-43DmfD33.js +0 -0
  314. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/powerquery-D3hlyOfw.js +0 -0
  315. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/powershell-DmHpPYUd.js +0 -0
  316. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/protobuf-C531GsRP.js +0 -0
  317. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/pug-Z5eAx3Zn.js +0 -0
  318. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/qsharp-DkqhCAOL.js +0 -0
  319. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/r-BwWrilGY.js +0 -0
  320. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/redis-ClamHrr6.js +0 -0
  321. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/redshift-DT7zqm-g.js +0 -0
  322. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/restructuredtext-BYgofb2h.js +0 -0
  323. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/ruby-DezsRK8O.js +0 -0
  324. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/rust-DdL9SqIa.js +0 -0
  325. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/sb-CcwsVR0C.js +0 -0
  326. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/scala-DHpiXF5c.js +0 -0
  327. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/scheme-BeGwcela.js +0 -0
  328. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/scss-gp-XZpBa.js +0 -0
  329. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/shell-CC2rA5mh.js +0 -0
  330. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/solidity-BEEn4gHE.js +0 -0
  331. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/sophia-CRfGWb83.js +0 -0
  332. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/sparql-D_Lu-MrJ.js +0 -0
  333. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/sql-NEE52Syq.js +0 -0
  334. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/st-DbInun42.js +0 -0
  335. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/swift-Bxkupp3x.js +0 -0
  336. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/systemverilog-Bz4Y3fRF.js +0 -0
  337. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/tcl-DISqw1ZD.js +0 -0
  338. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/ts.worker-DGGa2mF8.js +0 -0
  339. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/twig-De2hgUGE.js +0 -0
  340. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/typespec-B8J7ngcE.js +0 -0
  341. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/vb-DV3o63ZY.js +0 -0
  342. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/ui/assets/wgsl-DpFanUEy.js +0 -0
  343. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/updater.py +0 -0
  344. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/server/worker_memory.py +0 -0
  345. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/settings.py +0 -0
  346. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/shot_span_preflight.py +0 -0
  347. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/shots.py +0 -0
  348. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/slice_preflight.py +0 -0
  349. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/sparse_attention.py +0 -0
  350. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/step.py +0 -0
  351. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/step_cache.py +0 -0
  352. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/step_value_checks.py +0 -0
  353. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/subfolders.py +0 -0
  354. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/audio_handlers.py +0 -0
  355. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/audio_utils.py +0 -0
  356. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/beats.py +0 -0
  357. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/borders.py +0 -0
  358. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/compose_text.py +0 -0
  359. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/concat_videos.py +0 -0
  360. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/cuts.py +0 -0
  361. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/dissolve_videos.py +0 -0
  362. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/finish.py +0 -0
  363. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/finish_handlers.py +0 -0
  364. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/fit.py +0 -0
  365. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/format_messages.py +0 -0
  366. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/gather.py +0 -0
  367. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/grade.py +0 -0
  368. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/h3_latent_upscaler_model.py +0 -0
  369. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/image_ops.py +0 -0
  370. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/join_into_song.py +0 -0
  371. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/joins.py +0 -0
  372. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/loop_bed.py +0 -0
  373. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/lut.py +0 -0
  374. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/measure_sync.py +0 -0
  375. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/model_cache.py +0 -0
  376. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/qr_code.py +0 -0
  377. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/rife_model.py +0 -0
  378. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/select.py +0 -0
  379. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/stabilize.py +0 -0
  380. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/task.py +0 -0
  381. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/tensor_image.py +0 -0
  382. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/text_sections.py +0 -0
  383. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/trim.py +0 -0
  384. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/windows.py +0 -0
  385. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/tasks/zoe_depth.py +0 -0
  386. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/test.py +0 -0
  387. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/trust.py +0 -0
  388. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/type_helpers.py +0 -0
  389. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/type_references.py +0 -0
  390. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/validate.py +0 -0
  391. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/variable_constraints.py +0 -0
  392. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/variables.py +0 -0
  393. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/video_extensions.py +0 -0
  394. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/video_size_errors.py +0 -0
  395. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/window_count_errors.py +0 -0
  396. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/workflow.py +0 -0
  397. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/workflow_run.py +0 -0
  398. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/workflow_schema.json +0 -0
  399. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/workflows/flux3_klein_upsample.json +0 -0
  400. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/workflows/flux3_klein_upsample_edit.json +0 -0
  401. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/workflows/test.json +0 -0
  402. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/workspace.py +0 -0
  403. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/workspace_copy.py +0 -0
  404. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw/writers.py +0 -0
  405. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/__init__.py +0 -0
  406. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/__main__.py +0 -0
  407. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/assets.py +0 -0
  408. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/authoring.py +0 -0
  409. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/confine.py +0 -0
  410. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/diagnose.py +0 -0
  411. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/exports.py +0 -0
  412. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/guides.py +0 -0
  413. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/loras.py +0 -0
  414. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/media.py +0 -0
  415. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/models.py +0 -0
  416. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/prompts.py +0 -0
  417. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/server.py +0 -0
  418. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/tools_authoring.py +0 -0
  419. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/tools_jobs.py +0 -0
  420. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/tools_media.py +0 -0
  421. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/dw_mcp/workspaces.py +0 -0
  422. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/setup.cfg +0 -0
  423. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_admission_capacity.py +0 -0
  424. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_analyze_beats.py +0 -0
  425. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_arch_metrics.py +0 -0
  426. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_arch_report.py +0 -0
  427. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_architecture_map.py +0 -0
  428. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_argument_updates.py +0 -0
  429. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_arguments.py +0 -0
  430. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_assemble_and_score_target_lufs.py +0 -0
  431. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_assess.py +0 -0
  432. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_assessment_rules.py +0 -0
  433. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_assets.py +0 -0
  434. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_attention_backend_trace.py +0 -0
  435. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_attention_slicing.py +0 -0
  436. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_best_of_n_template.py +0 -0
  437. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_borders.py +0 -0
  438. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_cache_stats.py +0 -0
  439. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_catalog_shape.py +0 -0
  440. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_catalog_speed_defaults.py +0 -0
  441. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_chain.py +0 -0
  442. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_ci_config.py +0 -0
  443. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_cli.py +0 -0
  444. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_compare_route.py +0 -0
  445. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_component_name_errors.py +0 -0
  446. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_component_pruning.py +0 -0
  447. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_component_type_errors.py +0 -0
  448. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_compose_text.py +0 -0
  449. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_concat_videos.py +0 -0
  450. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_config_objects.py +0 -0
  451. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_configuration_schema.py +0 -0
  452. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_content_types.py +0 -0
  453. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_dependencies_declared.py +0 -0
  454. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_depth_estimator.py +0 -0
  455. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_device.py +0 -0
  456. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_device_helpers.py +0 -0
  457. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_device_portability.py +0 -0
  458. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_dialogue_short_voices.py +0 -0
  459. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_diffusion_upscale.py +0 -0
  460. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_disk_caches.py +0 -0
  461. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_dissolve_frame_errors.py +0 -0
  462. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_dissolve_videos.py +0 -0
  463. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_docs_links.py +0 -0
  464. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_download_watch.py +0 -0
  465. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_dsp.py +0 -0
  466. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_elision.py +0 -0
  467. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_events.py +0 -0
  468. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_examples.py +0 -0
  469. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_face_track.py +0 -0
  470. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_faststart.py +0 -0
  471. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_find_loop_bed.py +0 -0
  472. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_finish.py +0 -0
  473. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_fit_templates.py +0 -0
  474. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_fit_to_model.py +0 -0
  475. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_flux3_catalog.py +0 -0
  476. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_for_each.py +0 -0
  477. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_gather.py +0 -0
  478. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_grade.py +0 -0
  479. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_guide_chain_validation.py +0 -0
  480. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_guides_validation.py +0 -0
  481. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_adapters.py +0 -0
  482. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_guides.py +0 -0
  483. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_schedule.py +0 -0
  484. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_h3_sparse_defaults.py +0 -0
  485. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_hf_placement.py +0 -0
  486. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_host_memory.py +0 -0
  487. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_host_memory_projection.py +0 -0
  488. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_host_ram_need.py +0 -0
  489. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_hub_cache.py +0 -0
  490. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_image_ops.py +0 -0
  491. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_image_to_text.py +0 -0
  492. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_image_utils.py +0 -0
  493. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_inductor_cache_default.py +0 -0
  494. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_ingredients_grid.py +0 -0
  495. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_integration.py +0 -0
  496. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_interpolate_frames.py +0 -0
  497. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_introspection.py +0 -0
  498. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_job_history_device.py +0 -0
  499. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_job_history_wal.py +0 -0
  500. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_job_progress.py +0 -0
  501. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_job_warnings.py +0 -0
  502. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_jobs_listing.py +0 -0
  503. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_jobs_reused.py +0 -0
  504. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_join_into_song.py +0 -0
  505. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_join_windows.py +0 -0
  506. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_judge.py +0 -0
  507. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_kernel_availability.py +0 -0
  508. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_library_path.py +0 -0
  509. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_library_sources.py +0 -0
  510. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_list_images.py +0 -0
  511. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_lora_alpha.py +0 -0
  512. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_lora_catalog.py +0 -0
  513. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_lora_hub.py +0 -0
  514. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_lora_library.py +0 -0
  515. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_ltx2_diffusion_decode.py +0 -0
  516. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_ltx2_extend_clip.py +0 -0
  517. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_ltx2_ic_loras.py +0 -0
  518. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_ltx2_refine_pipeline.py +0 -0
  519. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_ltx_prompt_library.py +0 -0
  520. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_lut.py +0 -0
  521. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_assets.py +0 -0
  522. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_authoring.py +0 -0
  523. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_catalog.py +0 -0
  524. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_confine.py +0 -0
  525. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_diagnose.py +0 -0
  526. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_exports.py +0 -0
  527. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_guides.py +0 -0
  528. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_loras.py +0 -0
  529. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_main.py +0 -0
  530. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_media.py +0 -0
  531. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_models.py +0 -0
  532. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_prompts.py +0 -0
  533. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_twins.py +0 -0
  534. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mcp_workspaces.py +0 -0
  535. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_measure_sync.py +0 -0
  536. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_media_audio.py +0 -0
  537. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_media_compare.py +0 -0
  538. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_media_decode_threads.py +0 -0
  539. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_media_frames.py +0 -0
  540. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_media_info.py +0 -0
  541. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_media_layering.py +0 -0
  542. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mix_audio.py +0 -0
  543. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_model_cache.py +0 -0
  544. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_modular_pipeline.py +0 -0
  545. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mps_fallback_warning.py +0 -0
  546. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_mps_rope_precision.py +0 -0
  547. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_notes.py +0 -0
  548. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_notes_bookkeeping.py +0 -0
  549. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_null_media.py +0 -0
  550. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_numeric_coercion.py +0 -0
  551. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_offload_placement.py +0 -0
  552. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_output_references.py +0 -0
  553. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_pair_audio.py +0 -0
  554. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_pair_audio_fit.py +0 -0
  555. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_parallel_loading_default.py +0 -0
  556. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_path_redaction.py +0 -0
  557. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_phase_events.py +0 -0
  558. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_pipeline_caching.py +0 -0
  559. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_plan_cuts.py +0 -0
  560. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_prepare_pipeline.py +0 -0
  561. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_previous_result_walker_parity.py +0 -0
  562. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_previous_results.py +0 -0
  563. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_prompt_library.py +0 -0
  564. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_prompt_parser.py +0 -0
  565. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_prompt_references.py +0 -0
  566. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_prompt_weighting.py +0 -0
  567. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_prompts.py +0 -0
  568. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_quantized_cache.py +0 -0
  569. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_read_frame_range.py +0 -0
  570. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_real_models.py +0 -0
  571. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_realize.py +0 -0
  572. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_recenter_crop.py +0 -0
  573. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_reference_names.py +0 -0
  574. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_reference_skip_sets.py +0 -0
  575. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_references.py +0 -0
  576. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_rerun_lineage.py +0 -0
  577. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_rerun_new_seed.py +0 -0
  578. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_resize_bucket.py +0 -0
  579. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_restore_faces_helper_cache.py +0 -0
  580. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_restore_faces_video.py +0 -0
  581. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_result.py +0 -0
  582. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_result_fps.py +0 -0
  583. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_result_output_naming.py +0 -0
  584. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_rule_parity.py +0 -0
  585. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_run_manifest_roles.py +0 -0
  586. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_runs.py +0 -0
  587. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_runtime_settings.py +0 -0
  588. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_scalar_result_validation.py +0 -0
  589. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_scheduler_config.py +0 -0
  590. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_schema.py +0 -0
  591. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_security.py +0 -0
  592. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_security_auth.py +0 -0
  593. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_security_decoder_bombs.py +0 -0
  594. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_security_input_caps.py +0 -0
  595. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_security_symlinks.py +0 -0
  596. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_security_trust_gate.py +0 -0
  597. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_security_web_headers.py +0 -0
  598. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_select.py +0 -0
  599. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_select_validation.py +0 -0
  600. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_assess.py +0 -0
  601. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_downloads.py +0 -0
  602. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_exports.py +0 -0
  603. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_gallery_image.py +0 -0
  604. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_guides.py +0 -0
  605. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_info.py +0 -0
  606. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_library_path.py +0 -0
  607. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_loras.py +0 -0
  608. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_mcp.py +0 -0
  609. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_server_workspaces.py +0 -0
  610. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_shaping_logs.py +0 -0
  611. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_shot_span_preflight.py +0 -0
  612. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_shots.py +0 -0
  613. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_slice_preflight.py +0 -0
  614. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_sparse_attention_backends.py +0 -0
  615. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_sparse_attention_processor.py +0 -0
  616. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_sparse_attention_tiles.py +0 -0
  617. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_sparse_attention_wiring.py +0 -0
  618. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_speech_generation.py +0 -0
  619. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_stabilize.py +0 -0
  620. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_stars.py +0 -0
  621. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_step.py +0 -0
  622. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_step_timing.py +0 -0
  623. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_strip_exif_and_watermark.py +0 -0
  624. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_sub_workflow_resolver.py +0 -0
  625. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_subfolders.py +0 -0
  626. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_task.py +0 -0
  627. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_task_discovery.py +0 -0
  628. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_task_public_imports.py +0 -0
  629. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_task_registry_rules.py +0 -0
  630. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_task_signature_errors.py +0 -0
  631. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_template_defaults.py +0 -0
  632. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_template_subfolders.py +0 -0
  633. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_tensor_image.py +0 -0
  634. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_text_generation.py +0 -0
  635. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_text_sections.py +0 -0
  636. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_transcribe_audio.py +0 -0
  637. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_trim_video.py +0 -0
  638. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_type_helpers.py +0 -0
  639. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_type_helpers_concurrency.py +0 -0
  640. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_ui_twins.py +0 -0
  641. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_unbraced_type_warning.py +0 -0
  642. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_updater.py +0 -0
  643. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_validate_arguments.py +0 -0
  644. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_validation.py +0 -0
  645. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_variable_constraints.py +0 -0
  646. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_variables.py +0 -0
  647. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_video_extensions.py +0 -0
  648. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_video_size_errors.py +0 -0
  649. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_video_utils.py +0 -0
  650. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_voice_attribution.py +0 -0
  651. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_vram_guides.py +0 -0
  652. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_window_count_errors.py +0 -0
  653. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_window_video.py +0 -0
  654. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_worker.py +0 -0
  655. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_worker_job_peak_rss.py +0 -0
  656. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_worker_manager.py +0 -0
  657. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_worker_messages.py +0 -0
  658. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_worker_pool.py +0 -0
  659. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_workflow.py +0 -0
  660. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_workflow_run_keys.py +0 -0
  661. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_workflow_snapshot.py +0 -0
  662. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_workflow_step_cache.py +0 -0
  663. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_workflow_trust.py +0 -0
  664. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_workspace.py +0 -0
  665. {diffusers_workflow-0.15.0 → diffusers_workflow-0.16.0}/tests/test_workspace_copy.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffusers-workflow
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Summary: Declarative workflow engine and web UI for Hugging Face Diffusers
5
5
  Author: dkackman
6
6
  License: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffusers-workflow
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Summary: Declarative workflow engine and web UI for Hugging Face Diffusers
5
5
  Author: dkackman
6
6
  License: Apache-2.0
@@ -52,6 +52,7 @@ dw/output_extraction.py
52
52
  dw/path_redaction.py
53
53
  dw/pipeline_ownership.py
54
54
  dw/plan.py
55
+ dw/plan_downloads.py
55
56
  dw/previous_results.py
56
57
  dw/probe_paths.py
57
58
  dw/prompt_schema.json
@@ -135,6 +136,8 @@ dw/pipeline_processors/h3_guides.py
135
136
  dw/pipeline_processors/h3_hold.py
136
137
  dw/pipeline_processors/h3_hold_steps.py
137
138
  dw/pipeline_processors/h3_rules.py
139
+ dw/pipeline_processors/h3_tiles.py
140
+ dw/pipeline_processors/mag_calibration.py
138
141
  dw/pipeline_processors/pipeline.py
139
142
  dw/pipeline_processors/placement.py
140
143
  dw/pipeline_processors/progress.py
@@ -193,44 +196,44 @@ dw/server/ui/assets/csharp-BKxtCVv1.js
193
196
  dw/server/ui/assets/csp-bTuwJoIa.js
194
197
  dw/server/ui/assets/css-DIMkf-bt.js
195
198
  dw/server/ui/assets/css.worker-C6lDtRpF.js
196
- dw/server/ui/assets/cssMode-D_BuRO9Y.js
199
+ dw/server/ui/assets/cssMode-Cx99RWkL.js
197
200
  dw/server/ui/assets/cypher-CVaqCwHa.js
198
201
  dw/server/ui/assets/dart-onAF5SnQ.js
199
202
  dw/server/ui/assets/dockerfile-DZFCIeNp.js
200
203
  dw/server/ui/assets/ecl-D05T4iGw.js
201
204
  dw/server/ui/assets/editor-DjpsE8to.css
202
- dw/server/ui/assets/editor.api-B6pi6BSE.js
205
+ dw/server/ui/assets/editor.api-jKhYFhrF.js
203
206
  dw/server/ui/assets/editor.worker-BmdWdrHZ.js
204
207
  dw/server/ui/assets/elixir-6RTg0lbw.js
205
208
  dw/server/ui/assets/flow9-C5_-GSwl.js
206
- dw/server/ui/assets/freemarker2-mPiw3NV_.js
209
+ dw/server/ui/assets/freemarker2-Cr_kdwwJ.js
207
210
  dw/server/ui/assets/fsharp-C8Ef5oNN.js
208
211
  dw/server/ui/assets/go-C-y9NEjX.js
209
212
  dw/server/ui/assets/graphql-fmXr3nnJ.js
210
- dw/server/ui/assets/handlebars-BfGb596Y.js
213
+ dw/server/ui/assets/handlebars-CnbOycVf.js
211
214
  dw/server/ui/assets/hcl-CpzslTdj.js
212
- dw/server/ui/assets/html-xXIqw-JZ.js
215
+ dw/server/ui/assets/html-vCIOVoPc.js
213
216
  dw/server/ui/assets/html.worker-C5yZDBHz.js
214
- dw/server/ui/assets/htmlMode-B3FC_H4q.js
215
- dw/server/ui/assets/index-Civ6zDZP.js
216
- dw/server/ui/assets/index-PRSQwOeN.css
217
+ dw/server/ui/assets/htmlMode-B5ESZlHK.js
218
+ dw/server/ui/assets/index-Bm_jBlG4.css
219
+ dw/server/ui/assets/index-DIXj1Pp3.js
217
220
  dw/server/ui/assets/ini-sBoK_t0W.js
218
221
  dw/server/ui/assets/java-BEtHBSE6.js
219
- dw/server/ui/assets/javascript-B-FFcgST.js
222
+ dw/server/ui/assets/javascript-DpV2UaWD.js
220
223
  dw/server/ui/assets/json.worker-DdeUAmHa.js
221
- dw/server/ui/assets/jsonMode-BELbxUQD.js
224
+ dw/server/ui/assets/jsonMode-DaGlZZy1.js
222
225
  dw/server/ui/assets/julia-Bri6UV-V.js
223
226
  dw/server/ui/assets/kotlin-BOotOW0E.js
224
227
  dw/server/ui/assets/less-B9JPFI3C.js
225
228
  dw/server/ui/assets/lexon-CfSJPG6W.js
226
- dw/server/ui/assets/liquid-CxXhb7_e.js
227
- dw/server/ui/assets/lspLanguageFeatures-sXyBqSzn.js
229
+ dw/server/ui/assets/liquid-Ds835QKV.js
230
+ dw/server/ui/assets/lspLanguageFeatures-Cd9OxrIO.js
228
231
  dw/server/ui/assets/lua-CsQS60Ue.js
229
232
  dw/server/ui/assets/m3-D-oSqn_W.js
230
233
  dw/server/ui/assets/markdown-Cimd5fb3.js
231
- dw/server/ui/assets/mdx-4jPGQ4yb.js
234
+ dw/server/ui/assets/mdx-BozOHFIi.js
232
235
  dw/server/ui/assets/mips-CIPQ_RoX.js
233
- dw/server/ui/assets/monaco-ByFdQnrs.js
236
+ dw/server/ui/assets/monaco-673w9Wwq.js
234
237
  dw/server/ui/assets/monaco-n7clI0si.css
235
238
  dw/server/ui/assets/msdax-DauUninz.js
236
239
  dw/server/ui/assets/mysql-SOo6toE5.js
@@ -246,10 +249,10 @@ dw/server/ui/assets/powerquery-D3hlyOfw.js
246
249
  dw/server/ui/assets/powershell-DmHpPYUd.js
247
250
  dw/server/ui/assets/protobuf-C531GsRP.js
248
251
  dw/server/ui/assets/pug-Z5eAx3Zn.js
249
- dw/server/ui/assets/python-D3CL9Y6O.js
252
+ dw/server/ui/assets/python-D_HjE-WC.js
250
253
  dw/server/ui/assets/qsharp-DkqhCAOL.js
251
254
  dw/server/ui/assets/r-BwWrilGY.js
252
- dw/server/ui/assets/razor-F_hjmtqk.js
255
+ dw/server/ui/assets/razor-DjEZAQZw.js
253
256
  dw/server/ui/assets/redis-ClamHrr6.js
254
257
  dw/server/ui/assets/redshift-DT7zqm-g.js
255
258
  dw/server/ui/assets/restructuredtext-BYgofb2h.js
@@ -269,15 +272,15 @@ dw/server/ui/assets/swift-Bxkupp3x.js
269
272
  dw/server/ui/assets/systemverilog-Bz4Y3fRF.js
270
273
  dw/server/ui/assets/tcl-DISqw1ZD.js
271
274
  dw/server/ui/assets/ts.worker-DGGa2mF8.js
272
- dw/server/ui/assets/tsMode-BiyDvHYY.js
275
+ dw/server/ui/assets/tsMode-B3g7-HAd.js
273
276
  dw/server/ui/assets/twig-De2hgUGE.js
274
- dw/server/ui/assets/typescript-DBE1Uz0U.js
277
+ dw/server/ui/assets/typescript-Bq3yLFs6.js
275
278
  dw/server/ui/assets/typespec-B8J7ngcE.js
276
279
  dw/server/ui/assets/vb-DV3o63ZY.js
277
280
  dw/server/ui/assets/wgsl-DpFanUEy.js
278
- dw/server/ui/assets/workers-Ci7sZ35J.js
279
- dw/server/ui/assets/xml-Eqpmo6a1.js
280
- dw/server/ui/assets/yaml-BNP_JiwW.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
281
284
  dw/tasks/assess.py
282
285
  dw/tasks/audio_dynamics.py
283
286
  dw/tasks/audio_handlers.py
@@ -316,9 +319,11 @@ dw/tasks/model_handlers.py
316
319
  dw/tasks/pair_audio.py
317
320
  dw/tasks/qr_code.py
318
321
  dw/tasks/registry.py
322
+ dw/tasks/remove_object.py
319
323
  dw/tasks/restore_faces.py
320
324
  dw/tasks/rife_model.py
321
325
  dw/tasks/script_check.py
326
+ dw/tasks/script_take.py
322
327
  dw/tasks/segment.py
323
328
  dw/tasks/select.py
324
329
  dw/tasks/speech_generation.py
@@ -332,6 +337,7 @@ dw/tasks/upscale.py
332
337
  dw/tasks/video_handlers.py
333
338
  dw/tasks/video_utils.py
334
339
  dw/tasks/voice_attribution.py
340
+ dw/tasks/weights.py
335
341
  dw/tasks/windows.py
336
342
  dw/tasks/zoe_depth.py
337
343
  dw/workflows/flux3_klein_upsample.json
@@ -382,6 +388,7 @@ tests/test_catalog_shape.py
382
388
  tests/test_catalog_speed_defaults.py
383
389
  tests/test_catalog_structure.py
384
390
  tests/test_chain.py
391
+ tests/test_chain_h3_native.py
385
392
  tests/test_ci_config.py
386
393
  tests/test_cli.py
387
394
  tests/test_compare_route.py
@@ -422,6 +429,7 @@ tests/test_gallery_roles.py
422
429
  tests/test_gather.py
423
430
  tests/test_grade.py
424
431
  tests/test_guide_chain_validation.py
432
+ tests/test_guide_pointers.py
425
433
  tests/test_guides_validation.py
426
434
  tests/test_h3_adapters.py
427
435
  tests/test_h3_context_ir.py
@@ -432,6 +440,7 @@ tests/test_h3_refine.py
432
440
  tests/test_h3_rules.py
433
441
  tests/test_h3_schedule.py
434
442
  tests/test_h3_sparse_defaults.py
443
+ tests/test_h3_tiles.py
435
444
  tests/test_h3_upscaler_source.py
436
445
  tests/test_h3_vram_ceiling.py
437
446
  tests/test_hf_placement.py
@@ -449,6 +458,7 @@ tests/test_integration.py
449
458
  tests/test_interpolate_frames.py
450
459
  tests/test_introspection.py
451
460
  tests/test_job_history_device.py
461
+ tests/test_job_history_parity.py
452
462
  tests/test_job_history_wal.py
453
463
  tests/test_job_progress.py
454
464
  tests/test_job_warnings.py
@@ -539,6 +549,7 @@ tests/test_reference_limits.py
539
549
  tests/test_reference_names.py
540
550
  tests/test_reference_skip_sets.py
541
551
  tests/test_references.py
552
+ tests/test_remove_object.py
542
553
  tests/test_rerun_lineage.py
543
554
  tests/test_rerun_new_seed.py
544
555
  tests/test_resize_bucket.py
@@ -556,6 +567,7 @@ tests/test_scalar_result_validation.py
556
567
  tests/test_scheduler_config.py
557
568
  tests/test_schema.py
558
569
  tests/test_script_check.py
570
+ tests/test_seam_look.py
559
571
  tests/test_security.py
560
572
  tests/test_security_auth.py
561
573
  tests/test_security_decoder_bombs.py
@@ -601,9 +613,11 @@ tests/test_subfolders.py
601
613
  tests/test_task.py
602
614
  tests/test_task_discovery.py
603
615
  tests/test_task_domains.py
616
+ tests/test_task_file_weights.py
604
617
  tests/test_task_public_imports.py
605
618
  tests/test_task_registry_rules.py
606
619
  tests/test_task_signature_errors.py
620
+ tests/test_task_weights.py
607
621
  tests/test_template_defaults.py
608
622
  tests/test_template_subfolders.py
609
623
  tests/test_tensor_image.py
@@ -641,4 +655,5 @@ tests/test_workflow_snapshot.py
641
655
  tests/test_workflow_step_cache.py
642
656
  tests/test_workflow_trust.py
643
657
  tests/test_workspace.py
644
- tests/test_workspace_copy.py
658
+ tests/test_workspace_copy.py
659
+ tests/test_zimage_vram.py
@@ -91,7 +91,7 @@ SPARSE_FALLBACK = "sparse_attention_fallback"
91
91
  CACHE_UNSUPPORTED = "cache_unsupported"
92
92
 
93
93
  # The component names a cache hook attaches to, as in
94
- # dw.pipeline_processors.components.get_cache_transformer
94
+ # dw.pipeline_processors.mag_calibration.get_cache_transformer
95
95
  _CACHE_COMPONENTS = ("transformer", "transformer_ref")
96
96
 
97
97
 
@@ -312,6 +312,21 @@ DISABLED_MESSAGE = (
312
312
  )
313
313
 
314
314
 
315
+ # Step-distillation loras run in 4-9 steps; a null-lora step at or past this
316
+ # has already been given the base model's schedule, so the warning is stale.
317
+ RAISED_STEPS = 10
318
+
319
+
320
+ def _schedule_raised(pipeline):
321
+ arguments = pipeline.get("arguments")
322
+ steps = (
323
+ arguments.get("num_inference_steps") if isinstance(arguments, dict) else None
324
+ )
325
+ return (
326
+ isinstance(steps, int) and not isinstance(steps, bool) and steps >= RAISED_STEPS
327
+ )
328
+
329
+
315
330
  def _disabled_loras(steps, source_indices, written=None, supplied=()):
316
331
  """Every `loras` entry switched off with a null model_name, as
317
332
  (path, message). Any pipeline, not only H3: the off switch is the
@@ -322,7 +337,7 @@ def _disabled_loras(steps, source_indices, written=None, supplied=()):
322
337
  steps, source_indices, "pipeline"
323
338
  ):
324
339
  loras = pipeline.get(LORAS_KEY)
325
- if not isinstance(loras, list):
340
+ if not isinstance(loras, list) or _schedule_raised(pipeline):
326
341
  continue
327
342
  for position, lora in enumerate(loras):
328
343
  if not isinstance(lora, dict) or lora.get(MODEL_NAME_KEY) is not None:
@@ -220,7 +220,7 @@ def _with_frame_rate(frames, location):
220
220
  only looks at a real local path. A file that says neither stays a plain
221
221
  list.
222
222
  """
223
- from .tasks.video_utils import FrameList
223
+ from .media_types import FrameList
224
224
 
225
225
  if not isinstance(frames, list):
226
226
  return frames
@@ -273,7 +273,7 @@ def local_media_file(location, what, default_suffix=""):
273
273
 
274
274
  def _fetch_remote_video(url):
275
275
  """A video URL's frames, decoded from `local_media_file`'s copy."""
276
- from .tasks.video_utils import FrameList
276
+ from .media_types import FrameList
277
277
 
278
278
  with local_media_file(url, "a video argument", default_suffix=".mp4") as path:
279
279
  frames = load_video(path)
@@ -109,7 +109,7 @@ def check_device_present(device):
109
109
  raise DeviceConfigError(f"{device} is not available on this machine")
110
110
 
111
111
 
112
- def resolve_serve_devices(cli_value, settings_value):
112
+ def resolve_serve_devices(cli_value, settings_value, on_absent=None):
113
113
  """The devices a server runs on - `--devices`, else the `devices`
114
114
  setting - or None when neither names any, which leaves today's single
115
115
  device (`DW_DEVICE`, then the `device` setting, then detection) alone.
@@ -117,7 +117,14 @@ def resolve_serve_devices(cli_value, settings_value):
117
117
  More than one entry runs a worker per card, so each must be a card of
118
118
  its own. Raises DeviceConfigError for a duplicate, for an unindexed
119
119
  `cuda` in a list of several (it would not be pinned, and would share
120
- card 0), and for a device this machine does not have."""
120
+ card 0), and for a device this machine does not have.
121
+
122
+ A list of several survives a card being pulled: an absent entry is
123
+ dropped and its refusal passed to `on_absent`, so a box with a card
124
+ out for service comes up on the rest instead of refusing to start (a
125
+ service manager restarting it would loop forever). Only when no entry
126
+ is present - or `on_absent` is None - is the first absence raised, so
127
+ a lone typo (`cuda:7`) still refuses."""
121
128
  raw = cli_value if cli_value else settings_value
122
129
  devices = parse_devices(raw)
123
130
  if not devices:
@@ -139,9 +146,19 @@ def resolve_serve_devices(cli_value, settings_value):
139
146
  "--devices with several entries must name each CUDA card by "
140
147
  "index ('cuda:0,cuda:1'), not a bare 'cuda'"
141
148
  )
149
+ present, absences = [], []
142
150
  for device in devices:
143
- check_device_present(device)
144
- return devices
151
+ try:
152
+ check_device_present(device)
153
+ except DeviceConfigError as absence:
154
+ absences.append(absence)
155
+ else:
156
+ present.append(device)
157
+ if absences and (not present or on_absent is None):
158
+ raise absences[0]
159
+ for absence in absences:
160
+ on_absent(str(absence))
161
+ return present
145
162
 
146
163
 
147
164
  def _explicit_cuda_index(device):
@@ -32,7 +32,7 @@ one to open.
32
32
  | LoRAs | `dw/pipeline_processors/adapters.py`: `active_loras`, `load_loras` | A `loras` entry whose `model_name` is null is switched off. | `tests/test_lora_disable.py::TestLoadLoras::test_an_all_null_entry_loads_nothing` |
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
- | 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`, `get_cache_transformer` | 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 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` |
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
36
  | 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
37
  | 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
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` |
@@ -67,12 +67,14 @@ one to open.
67
67
  | Concept | Owner | Rule | Enforced by |
68
68
  | --- | --- | --- | --- |
69
69
  | Run directories | `dw/runs.py`: `open_run`, `workflow_identity`, `new_run_id` | Each execution writes into `<output_dir>/<identity>/<run id>/` with a `manifest.json`, unless the flat layout is chosen (the test pins the flat-layout exception). | `tests/test_runs.py::TestRunDirectories::test_the_flat_layout_writes_where_it_always_did` |
70
- | A file's role (final / intermediate / input) | `dw/roles.py` | Decided per step: result.role, then a final/intermediate subfolder, then data flow (a step a media-writing or unsaved consumer reads is intermediate). Engine records it at run end, with `role_declared` where result.role stated it; the server reports only recorded roles, so an older run has none. At read time the gallery (`GET /api/gallery`, its `role=` filter, the metadata route) also demotes a file a later run of the same workspace read - an `output:` input (an unpinned `latest` is the newest run started before the reader) or an `asset:` keep_output kept from it - unless its role was declared (`consumed_outputs`, `listed_role`, once per listing; no manifest is rewritten). | `tests/test_roles.py`, `tests/test_roles.py::test_a_file_a_later_run_read_is_consumed`, `tests/test_roles.py::test_listed_role`, `tests/test_gallery_roles.py::test_a_file_a_later_run_read_lists_as_intermediate`, `tests/test_gallery_roles.py::test_a_declared_final_stays_final` |
70
+ | A file's role (final / intermediate / input) | `dw/roles.py` | Decided per step: result.role, then a final/intermediate subfolder, then data flow (a step a media-writing or unsaved consumer reads is intermediate). Engine records it at run end, with `role_declared` where result.role stated it; a run that predates roles recorded none, so the listing falls back on the file's own `final`/`intermediate` subfolder, then the demotion below, and a file neither places has none. At read time the gallery (`GET /api/gallery`, its `role=` filter, the metadata route) also demotes a file a later run of the same workspace read - an `output:` input (an unpinned `latest` is the newest run started before the reader) or an `asset:` keep_output kept from it - unless its role was declared (`consumed_outputs`, `listed_role`, once per listing; no manifest is rewritten). | `tests/test_roles.py`, `tests/test_roles.py::test_a_file_a_later_run_read_is_consumed`, `tests/test_roles.py::test_listed_role`, `tests/test_roles.py::test_listed_role_of_a_run_that_recorded_none`, `tests/test_gallery_roles.py::test_older_run_reads_its_intermediate_subfolder_as_intermediate`, `tests/test_gallery_roles.py::test_a_pre_roles_file_a_later_run_read_lists_as_intermediate`, `tests/test_gallery_roles.py::test_metadata_agrees_with_the_listing_for_an_older_run`, `tests/test_gallery_roles.py::test_a_file_a_later_run_read_lists_as_intermediate`, `tests/test_gallery_roles.py::test_a_declared_final_stays_final` |
71
71
  | Notes on runs, files, assets, workspaces | dw/notes.py | notes.json beside what it describes (run dir or asset dir; a file's own note else the run's), workspace.json at a workspace root; only the server writes them, never the engine; ≤4000 chars, plain text. | tests/test_notes.py |
72
72
  | Run versions | `dw/runs.py`: `open_run`, `run_versions`, `record_run_versions`, `copy_runs_in` | A run takes its number once, when it opens (or, copied in from another workspace, when `copy_runs_in` places it), so deleting a middle run leaves a gap rather than renumbering. | `tests/test_runs.py::TestRunVersions::test_a_deleted_middle_run_leaves_a_gap_rather_than_renumbering`, `tests/test_runs.py::TestRunVersions::test_runs_started_in_the_same_second_still_number_upward` |
73
73
  | Run-version surfaces | `dw/runs.py`: `run_versions`, `dw/server/routes/gallery.py`, `dw/server/outputs.py`, `dw_mcp/tools_catalog.py`: `list_gallery`, `ui/src/lib/pages/GalleryPage.svelte` | Only `dw/runs.py` computes the number, and every other module reads it back. | `tests/test_runs.py::TestRunVersions::test_an_output_reference_can_name_a_run_by_its_version` |
74
+ | What the server says about an output file | `dw/server/outputs.py`: `output_annotations` | The gallery listing (`dw/server/routes/gallery.py`) and the metadata route (`dw/server/routes/media.py`) describe an output file's `role`, `note`, `note_source`, `run_note`, `starred` and `version` through `output_annotations`, and neither builds those fields on its own. | `tests/test_gallery_roles.py::test_metadata_agrees_with_the_listing_on_a_starred_noted_demoted_file` |
74
75
  | 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` |
75
76
  | 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
+ | 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) |
76
78
  | 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` |
77
79
  | 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` |
78
80
  | 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` |
@@ -95,20 +97,22 @@ one to open.
95
97
  | Admission | `dw/server/admission.py`: `admit` | Validate, submit, rerun and enhance load and check a request once, and `JobManager.submit` does not check it again. | `tests/test_admission.py::test_a_submit_expands_once` |
96
98
  | 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` |
97
99
  | 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` |
98
- | Per-repo gating | `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` |
100
+ | 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` |
102
+ | 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` |
99
103
  | 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` |
100
104
  | 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` |
101
105
  | Cost drivers | `dw/server/observed_cost.py`: `declared_drivers` | A cost driver that names no declared variable is dropped. | `tests/test_observed_cost.py::TestComparability::test_a_driver_naming_no_variable_is_dropped`, `tests/test_observed_cost.py::TestTheCatalogsDriversAreReal::test_every_declared_driver_is_a_variable_of_its_workflow` |
102
106
  | Raw workflow GET | `dw/server/routes/library.py`: `get_workflow` | The raw workflow GET is served verbatim, with no `observed`, because the editor saves what it reads. | — |
103
107
  | VRAM projection | `dw/vram_estimate.py`, `dw/guides.py`: `guide_lengths` | A template's `vram_estimate` is projected per step after `for_each` expansion, and only the largest step over the ceiling is reported. With `bytes_per_guide_voxel` declared, each guide the step lays in (its own non-null `guides` plus a guide chain's) adds its snapped frames times the canvas; an unprobeable clip is charged at `num_frames`, and validate, admission and run project the same number. | `tests/test_vram_estimate.py::test_only_the_largest_over_ceiling_step_is_reported_once_per_cost_entry`, `tests/test_vram_guides.py::test_validate_apply_and_required_agree_on_a_guided_definition` |
104
108
  | H3 Ref2VA VRAM numbers | `workflows/templates/minimax/` | Every Ref2VA template declares `base_gb` 16.0, `bytes_per_voxel` 28.71 and `gb_per_reference` 1.0. | `tests/test_h3_vram_ceiling.py::test_every_ref2va_minimax_template_declares_gb_per_reference` |
105
- | Inherited VRAM ceiling | `dw/vram_inheritance.py`, `dw/server/deps.py`: `ceiling_index` (the catalog parse is `_catalog_listing`, shared with the cost lookup below) | A workflow with no `vram_estimate` is matched against the catalog by pipeline identity, and is warned, never refused. | `tests/test_vram_inheritance.py::test_every_template_declaring_one_identity_declares_the_same_numbers` |
109
+ | Inherited VRAM ceiling | `dw/vram_inheritance.py`, `dw/server/deps.py`: `ceiling_index` (the catalog parse is `_catalog_listing`, shared with the cost lookup below) | A workflow with no `vram_estimate` is matched against the catalog by pipeline identity, and is warned, never refused. Under the ceiling it still gets a `vram_config_differs` warning when its offload or quantization differs from the template's, which the estimate was calibrated on (#954). | `tests/test_vram_inheritance.py::test_every_template_declaring_one_identity_declares_the_same_numbers`, `tests/test_vram_inheritance.py::TestConfigDiffers::test_missing_offload_under_the_ceiling_notes_it` |
106
110
  | Inherited cost | `dw/server/deps.py`: `inherited_observed`, `dw/vram_inheritance.py`: `inherited_differences`, `dw/plan.py`: `_observed` (basis `inherited`), `dw/server/routes/jobs.py`: `_inherited_cost_warnings` | An inline workflow (no catalog name) is priced from the observed runs of the catalog template with the same `component_type` + `model_name` + `workflow` key as `vram_inheritance`; the template with the most cold runs wins, then name. `differs` lists offload, quantization, frame count, attention backend, cache, LoRA and reference count (the `references` list lengths, per-entry `item:` ones read off the `for_each` list; named, not scaled, #915) set differently from the template, and sets `low_confidence` when it lists any (#866). More pipeline steps than the template run (a `for_each` counted per member, against the list the bucket ran, so a fallback to the default bucket re-prices a longer list) re-price its minutes linearly, and the mean frames, inference steps, width and height per pipeline step are scaled by `scale_curated` itself - the one rule the catalog figure uses, so an inline copy and its template quote one request alike - with `scaled` naming why and `low_confidence` set (#851, #866). It is warned, never refused. | `tests/test_inherited_cost.py::TestPricedByPipelineIdentity::test_an_inline_copy_inherits_the_templates_runs`, `tests/test_inherited_cost.py::TestDifferences::test_offload_quantization_and_frames_are_named`, `tests/test_inherited_cost.py::TestDifferences::test_a_reference_count_other_than_the_templates_is_named`, `tests/test_inherited_cost.py::TestThePlanReportsIt::test_the_estimate_is_inherited_and_the_validate_answer_warns`, `tests/test_inherited_cost.py::TestTheTemplateAndAnInlineCopyAgree::test_the_same_minutes_within_rounding`, `tests/test_inherited_cost.py::TestAListLongerThanTheFallbackBucket::test_an_inline_six_shot_copy_scales_by_members` |
107
111
  | Projected host-RAM peak | `dw/server/host_ram_need.py`: `memory_key`, `projected_peak`, `host_memory_block`; the fit is `dw/host_memory_projection.py`: `projected_mb`; history by key is `dw/server/job_history.py`: `peaks_for_key` | A run's memory key is the sorted pipeline identity of its pipeline steps plus every `quantization_config` / `offload` / `group_offload` value, with arguments substituted through `replace_variables`; never the workflow's name, so a renamed or inline copy shares the template's history. `observed` is the max peak over this machine's successful same-key runs and comes ahead of the list-run fit, unless the shape holds its pipeline across the list and the fit is the larger (the key leaves list length out, #910); with neither there is no figure. It never refuses; dispatch may delay a start on it (`dw/server/dispatch.py`: `Dispatcher._next_dispatch`, #869) (`Admission.host_ram_need`, validate's `plan.host_memory`). | `tests/test_host_ram_need.py::TestMemoryKey::test_an_inline_copy_without_its_metadata_has_the_same_key`, `tests/test_host_ram_need.py::TestMemoryKey::test_a_different_weights_dtype_is_a_different_key`, `tests/test_host_ram_need.py::TestProjectedPeak::test_an_observed_peak_beats_the_fit`, `tests/test_host_ram_need.py::TestALongerListThanObserved::test_an_accumulating_list_takes_the_larger_fit`, `tests/test_host_ram_need.py::TestProjectedPeak::test_a_failed_run_is_not_observed`, `tests/test_host_ram_need.py::TestValidateRoute::test_an_observed_run_is_the_plans_host_memory` |
108
112
  | 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` |
109
113
  | 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` |
110
114
  | 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` |
111
- | H3 audio hold, refine and guide layout | Five 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 asked before validation and before the call; `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`), 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/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`. 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_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` |
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` |
112
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` |
113
117
  | 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` |
114
118
  | 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` |
@@ -122,7 +126,7 @@ one to open.
122
126
  | A different result | `dw/server/routes/jobs.py`, `dw_mcp/tools_jobs.py`: `rerun_job` | `rerun` with `new_seed` draws a fresh seed into the workflow's seed variable. | `tests/test_rerun_new_seed.py::test_a_rerun_with_a_new_seed_draws_one_into_that_variable` |
123
127
  | Worker protocol | `dw/worker_protocol.py`: `parse_reply` | Every command and reply is a frozen dataclass that travels as a wire dict. A run event's keys sit beside the wire's own `type`, so an event's `type` key (`cache_stats`' cache type) crosses as `event_type` and comes back as `type`. | `tests/test_worker_messages.py::test_from_wire_inverts_to_wire`, `tests/test_cache_stats.py::test_the_event_crosses_the_worker_wire_with_its_cache_type`, `tests/test_worker_messages.py::test_an_unknown_reply_type_is_kept_whole_rather_than_raised` |
124
128
  | Persistent worker | `dw/worker.py`, `dw/worker_manager.py`, `dw/serve.py` | Jobs run in spawned workers (one per card) that keep models loaded, so a change to engine code needs a server restart. | — |
125
- | Worker card pinning | `dw/devices.py`: `worker_environment`, `pinned_environment`, `resolve_serve_devices`, `check_device_present`, `label_of` | A worker named with a CUDA index is spawned with `CUDA_VISIBLE_DEVICES` set to that card and `DW_DEVICE=cuda` (a bare `cuda` pins nothing), so index-0 reads inside it measure its own card; `--devices`/`devices` takes one entry per worker (a card named twice, or a bare `cuda` in a list of several, is refused), a card the box lacks is refused at startup naming the cards present, and a job stores the card it ran on as `device_ordinal` and `device_card` (#693), job and history alike: rerun affinity reads the ordinal, observed cost buckets by the card, and the `device` label `"cuda:N <card name>"` is only `label_of` joining the two - nothing splits a label back apart. | `tests/test_worker_manager.py::TestWorkerPinning::test_a_cuda_index_pins_the_worker_through_the_environment`, `tests/test_worker_manager.py::TestWorkerPinning::test_a_bare_cuda_sets_no_pin`, `tests/test_serve_main.py::TestConfigureDevices::test_a_refusal_exits_with_code_2`, `tests/test_serve_main.py::TestResolveServeDevices::test_a_card_the_machine_lacks_is_refused_naming_the_cards_present`, `tests/test_serve_main.py::TestResolveServeDevices::test_two_entries_are_both_kept`, `tests/test_serve_main.py::TestResolveServeDevices::test_a_card_named_twice_is_refused` |
129
+ | Worker card pinning | `dw/devices.py`: `worker_environment`, `pinned_environment`, `resolve_serve_devices`, `check_device_present`, `label_of` | A worker named with a CUDA index is spawned with `CUDA_VISIBLE_DEVICES` set to that card and `DW_DEVICE=cuda` (a bare `cuda` pins nothing), so index-0 reads inside it measure its own card; `--devices`/`devices` takes one entry per worker (a card named twice, or a bare `cuda` in a list of several, is refused), a card the box lacks is refused at startup naming the cards present (in a list of several it is dropped with a warning and the server starts on the rest; only a list with no card present refuses), and a job stores the card it ran on as `device_ordinal` and `device_card` (#693), job and history alike: rerun affinity reads the ordinal, observed cost buckets by the card, and the `device` label `"cuda:N <card name>"` is only `label_of` joining the two - nothing splits a label back apart. | `tests/test_worker_manager.py::TestWorkerPinning::test_a_cuda_index_pins_the_worker_through_the_environment`, `tests/test_worker_manager.py::TestWorkerPinning::test_a_bare_cuda_sets_no_pin`, `tests/test_serve_main.py::TestConfigureDevices::test_a_refusal_exits_with_code_2`, `tests/test_serve_main.py::TestResolveServeDevices::test_a_card_the_machine_lacks_is_refused_naming_the_cards_present`, `tests/test_serve_main.py::TestResolveServeDevices::test_two_entries_are_both_kept`, `tests/test_serve_main.py::TestResolveServeDevices::test_a_card_gone_from_a_list_is_dropped_and_reported`, `tests/test_serve_main.py::TestConfigureDevices::test_a_pulled_card_in_the_setting_starts_on_the_rest_and_warns`, `tests/test_serve_main.py::TestResolveServeDevices::test_a_card_named_twice_is_refused` |
126
130
  | Failed-run reporting | `dw/worker.py`, `dw/worker_protocol.py`: `Failed`, `Cancelled` | A failed or cancelled run's reply still carries the manifest of the steps that ran. | `tests/test_worker_execute.py::test_failure_carries_the_manifest_of_the_steps_that_ran`, `tests/test_worker_execute.py::test_cancellation_carries_the_manifest_too` |
127
131
  | Failure path redaction | `dw/path_redaction.py`: `redact_paths`, called by `dw/worker.py` | A failed run's message and traceback name a file under the job's asset roots or output directory by its `asset:`/`output:` reference, never its absolute server path. | `tests/test_worker_execute.py::test_a_failure_names_an_asset_by_reference_not_by_server_path`, `tests/test_path_redaction.py` |
128
132
  | Run-time warnings | `dw/events.py`: `emit_warning` | A warning found at run time is emitted as an event, so it reaches the caller and not just the log. | `tests/test_concat_videos.py::TestWarningsReachTheCaller::test_the_level_spread_warning_is_emitted_as_an_event` |
@@ -136,7 +140,7 @@ one to open.
136
140
  | 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` |
137
141
  | 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` |
138
142
  | 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` |
139
- | Script check | `dw/tasks/script_check.py`: `check`; `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_check.word_level` wraps it), 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` |
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` |
140
144
  | 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` |
141
145
 
142
146
  ## Security and architecture guardrails
@@ -168,6 +172,7 @@ one to open.
168
172
  | dw disk caches | `dw/disk_caches.py`; `dw/server/jobs.py`: `JobManager.hold_dispatch`; `dw/server/routes/system.py`: `clear_cache`, `delete_cache_entry` | Members `inductor`, `triton`, `quantized`. Clear only a root carrying the `.dw-cache` marker, never while a job is running or queued (`quantized` also not during a model download); an entry delete takes only a 64-hex id, checked before any path is built; clear renames into `.clearing-*` then deletes. The busy check and the dispatch hold are one step in `JobManager.hold_dispatch`, kept for the whole clear or entry delete: a job submitted meanwhile is accepted but stays queued until it ends. | `tests/test_disk_caches.py`, `tests/test_disk_caches.py::test_job_submitted_during_a_clear_waits_for_it` |
169
173
  | Job-to-run link | `dw/server/job_record.py`, `dw/server/jobs.py`: `JobManager.realized` | A job records `run_id`, `run_dir` and `run_version`, and `JobManager.realized` reads that run's `workflow.json`, confined to the output root. | `tests/test_server_jobs.py::test_realized_reads_the_file_the_run_wrote`, `tests/test_server_jobs.py::test_realized_refuses_a_run_dir_that_escapes_the_output_root` |
170
174
  | Job history | `dw/server/job_history.py`: `JobHistory`, `_ADDED_COLUMNS` | Finished jobs persist in `jobs.sqlite`, in WAL mode, so the Jobs view survives a restart. A database from an older release gains each column it lacks from the `_ADDED_COLUMNS` table when it is opened. | `tests/test_server.py::test_job_history_survives_restart_and_reruns`, `tests/test_job_history_wal.py::test_the_jobs_database_uses_wal_mode`, `tests/test_server_jobs.py::test_a_v0_13_0_database_gains_the_columns_added_since` |
175
+ | Job fields, live and persisted | `dw/server/job_record.py`: `Job.summary`, `Job.detail`; `dw/server/job_history.py`: `_RECORDED`, `_ADDED_COLUMNS`, `recent_summaries`, `_to_detail` | A job field is declared once per side: on `Job` (and its `summary()`/`detail()`), and in history as an `_ADDED_COLUMNS` entry plus one `(column, getter)` in `_RECORDED`. History readers take columns by name, never by position, and a historical job serves the same summary and detail keys a live one does, apart from the live-only poll state and the history-only markers the parity test declares. | `tests/test_job_history_parity.py::test_history_serves_the_keys_a_live_job_does` |
171
176
  | HTTP security | `dw/server/http_security.py`: `install_middleware`, `query_token_ok` | Every API route needs the token, and only a route marked `query_token_ok` takes it as `?token=`. | `tests/test_security_auth.py::TestTheTokenGate::test_every_api_spelling_needs_the_token`, `tests/test_security_auth.py::TestTheTokenGate::test_the_query_token_is_refused_where_it_is_not_allowed` |
172
177
  | Prompt enhancement | `dw/server/enhancers.py`: `PRESETS`, `_T2I_SYSTEM_PROMPT` | `PRESETS` is the Enhance panel's menu (label, curated LLMs, preselect hints); a preset's family-specific knowledge, its spec, lives in a builtin under `dw/workflows/`, never in Python. `t2i`'s generic, family-agnostic system prompt stays in Python. A third preset moves the menu into builtin metadata (#696). | `tests/test_prompt_library.py::test_every_enhancer_preset_targets_a_known_family`, `tests/test_server.py::TestEnhance::test_presets_are_listed`, `tests/test_server.py::TestEnhance::test_enhance_workflows_are_schema_valid`, `tests/test_server.py::TestEnhance::test_an_unknown_preset_is_a_client_error` |
173
178
 
@@ -178,6 +183,7 @@ one to open.
178
183
  | `dw_mcp` stays torch-free | `dw_mcp/` | `dw_mcp` reaches `dw.serve` over HTTP and imports no `dw` module, because `dw/__init__.py` pulls in torch. | `tests/test_mcp_server.py::TestStartupWeight::test_the_server_starts_without_importing_the_engine` |
179
184
  | Tool surface | `dw_mcp/server.py`, `dw_mcp/tools_*.py` | Only these modules import the MCP SDK, and each tool body is a one-line call into a handler. | `tests/test_mcp_server.py::test_the_wiring_table_covers_every_registered_tool`, `tests/test_mcp_server.py::test_the_stated_tool_count_is_the_registered_one` |
180
185
  | Surface text budget | the tool docstrings in `dw_mcp/tools_*.py`, the instructions in `dw_mcp/server.py` | The instructions and each tool description stay at or under 2,048 characters, and the whole surface stays within its token budget. | `tests/test_mcp_server.py`: `SURFACE_BUDGET`, `CLIENT_TEXT_LIMIT`; `tests/test_mcp_server.py::test_no_text_the_agent_reads_is_cut_off_by_the_client`, `tests/test_mcp_server.py::test_the_tool_surface_fits_the_budget` |
186
+ | Guide pointers in resident text | the tool docstrings in `dw_mcp/tools_*.py`, the instructions in `dw_mcp/server.py`, each plugin `SKILL.md` and its `references/` | Every `get_guide(...)` / guide-section pointer opens a real section through `dw/server/guides.py`'s `get_guide`, and the tools that point at a guide keep their pointer when text is trimmed to fit the budget. | `tests/test_guide_pointers.py` (`TOOLS_THAT_POINT`) |
181
187
  | Spending needs consent | each handler behind a tool that takes `acknowledged_cost` (`dw_mcp/diagnose.py`, `models.py`, `prompts.py`, `workspaces.py`) | Every tool that takes `acknowledged_cost` refuses until it is set; `delete_workspace`'s refusal is the server's 409. | `tests/test_mcp_twins.py::test_every_tool_that_takes_acknowledged_cost_refuses_without_it` |
182
188
  | Copies of engine rules | the constants and word lists in `dw_mcp/` and `dw/run.py` | `dw_mcp` cannot import its owners, so each copy equals its owner; a copy that needs no twin is deleted, not pinned. | `tests/test_mcp_twins.py` |
183
189
  | The CLI is a client of the server | `dw/run.py` | `dw.run` queues on `dw.serve` through `dw_mcp.client`, so `dw` imports `dw_mcp` and never the reverse. | `tests/test_mcp_server.py::TestStartupWeight::test_the_server_starts_without_importing_the_engine`, `tests/test_mcp_twins.py` |
@@ -47,7 +47,7 @@ pyproject; install.ps1 installs it explicitly on Windows.
47
47
 
48
48
  ## Platform-Specific Dependencies
49
49
 
50
- **All platforms (core ML):** peft, transformers, accelerate, safetensors, controlnet_aux, sentencepiece, torchsde, torchao, optimum-quanto, gguf, kornia, ftfy, sdnq, spandrel, facexlib (spandrel + facexlib back the `upscale` and `restore_faces` tasks). On first use, `restore_faces` has facexlib download its face detection and parsing weights (about 110 MB) from facexlib's own GitHub releases into the facexlib package directory. It is the one model download that bypasses the Hugging Face cache, dw's download manager and the `plan.downloads_required` estimate.
50
+ **All platforms (core ML):** peft, transformers, accelerate, safetensors, controlnet_aux, sentencepiece, torchsde, torchao, optimum-quanto, gguf, kornia, ftfy, sdnq, spandrel, facexlib (spandrel + facexlib back the `upscale` and `restore_faces` tasks). On first use, `restore_faces` has facexlib download its face detection and parsing weights (about 110 MB) from facexlib's own GitHub releases into the facexlib package directory. It is the one model download that bypasses the Hugging Face cache and dw's download manager; a validate's `plan.downloads_required` lists the two weights as URL entries while they are missing from that directory.
51
51
 
52
52
  **All platforms (sparse attention):** comfy-kitchen (Sol-Attn sparse attention for MiniMax H3's generated-video rows, #931). Its compiled CUDA/HIP kernels ship for Linux and Windows; elsewhere it installs an eager-only build.
53
53