| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [View Raw Code] [Original HTTPS Page] |
This map says where each concept lives. Each row names a concept, the module that owns it, the rule that holds across the seam (in one sentence), and what enforces that rule. The detail is in the owning module's docstring. Read the docstring before editing; the map only tells you which one to open.
Owner: repo-relative paths. Function, class or constant names follow the path after a colon (dw/runs.py: run_versions).
Enforced by: one of four kinds.
A — means nothing mechanical holds the rule, so a change there is caught only in review.
tests/test_architecture_map.py checks three things: every path named here exists, every name after a path is defined in that file, and every test named here is defined in its class.
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| Workflow | dw/workflow.py: Workflow, workflow_from_file | A workflow is loaded and schema-checked here (the hand-off of each run phase to dw/workflow_run.py: —). | tests/test_workflow.py::test_workflow_validation_invalid |
| One execution, in phases | dw/workflow_run.py: prepare_definition, cache_lookup, cache_hits | The cache probe shares prepare_definition and cache_lookup with the run, so the probe answers for the run that would happen. | tests/test_workflow_step_cache.py::TestCacheHits::test_after_a_run_the_probe_names_what_the_next_run_reuses |
| Step | dw/step.py: Step, dw/workflow.py: Workflow.create_step_action | A step is a pipeline, a task or a sub-workflow, create_step_action builds its action, and dw/workflow_run.py runs it. | — |
| Pipeline loading | dw/pipeline_processors/pipeline.py: Pipeline, dw/pipeline_processors/components.py: load_component | A quantization config is built from a config_type that the _type key convention loads by name, so a new backend needs no code. | tests/test_config_objects.py::TestQuantizationConfiguration::test_the_config_type_is_constructed_with_its_arguments |
| Device translation | dw/pipeline_processors/placement.py: place_component | A device is translated by resolve_device() before anything reads its backend, so the MPS accommodations also fire for a translated device. | tests/test_device_portability.py::TestPlacement::test_a_translated_device_gets_its_backends_offload_downgrade |
| On-demand wrappers | dw/pipeline_processors/placement.py: apply_on_demand_placement | The on-demand wrappers keep the wrapped signature, because H3's denoiser reads signature(transformer.forward). | tests/test_modular_pipeline.py::TestOnDemandResidency::test_the_wrapped_signature_survives |
| On-demand and offload | dw/pipeline_processors/placement.py: place_component, has_component_group_offload | On-demand residency and group_offload cannot both be set on one component, and either one stops the whole pipeline from being moved to the device. | tests/test_modular_pipeline.py::TestOnDemandResidency::test_group_offload_and_on_demand_together_are_rejected, tests/test_modular_pipeline.py::TestOffloadDevice::test_component_group_offload_is_not_moved_to_device |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| Variables | dw/variables.py: set_variables, argument_errors, resolve_variable_values | argument_errors folds a caller's arguments in exactly as set_variables does when a run starts, so a bad name or value is refused before anything is queued. | tests/test_variables.py::test_argument_errors_reports_a_dict_passed_for_a_string_variable |
| List variables from the CLI | dw/run.py, dw/variables.py: get_value | A name=value string given for a list variable is split on commas, so a list of objects can only be passed as JSON over the API or MCP. | tests/test_variables.py::test_set_variables_list_default_splits_on_comma |
| for_each expansion | dw/for_each.py: expand_for_each | Each entry becomes an ordinary step named <step>@<entry>, after substitution and before the reference check. | tests/test_for_each.py::TestNaming::test_member_name_joins_with_at |
| Optional entry field | dw/for_each.py: _optional_item, _item_fields | {"item": "field", "default": X} reads an entry field with a fallback; without default it is the plain required read, and list_fields / entry_field_warnings count the field as one entries take. The editor's string scan needs no twin code, only the shared case file. | tests/test_for_each.py::TestOptionalItem::test_a_present_field_wins_and_an_absent_one_takes_the_default, tests/test_ui_twins.py::test_the_engine_decides_each_shared_reference_case |
| Previous results | dw/previous_results.py: get_iterations, previous_result_reference_errors | Several previous_result: references in one step multiply into a cartesian product. | tests/test_previous_results.py::TestGetIterations::test_multiple_references_create_cartesian_product |
| Previous-result check | dw/previous_results.py: previous_result_reference_errors | A literal reference to a step that is not earlier in the workflow is a validation error. | tests/test_previous_results.py::TestStaticReferenceChecking::test_a_step_cannot_reference_itself_or_a_later_one |
| Type conversion | dw/arguments.py: realize_args, dw/type_helpers.py: get_type | A key ending _type or _dtype loads a Python object at realize time. The other spellings, and {} escaping, are in docs/WORKFLOW_GUIDE.md. | tests/test_type_helpers.py::TestGetType::test_get_type_from_diffusers, tests/test_arguments.py::TestRealizeArgs::test_realize_escaped_type_reference |
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| Reference prefixes | dw/references.py | Every reference prefix is spelled only in this module, and every other module goes through it. | docs/stabilization/baseline.json: prefix_literals, prefix_handling; tests/test_references.py::test_references_imports_nothing_from_dw |
| Explicit references resolve first | dw/arguments.py: _realize_explicit_reference | asset:, output:, constant: and prompt: resolve in realize_args before any key-name convention. | — |
| Reference confinement | dw/assets.py: resolve_asset_reference, dw/runs.py: resolve_output_reference, dw/library.py: LibraryPath, dw/security.py: validate_asset_reference, validate_output_reference | dw/security.py validators confine an asset: path to its library and an output: path to the output root. | tests/test_assets.py::TestReferences::test_a_symlink_out_of_the_library_is_refused, tests/test_security_symlinks.py::TestOutputs::test_an_output_reference_does_not_follow_a_linked_run_directory |
| Reference name shape | dw/reference_names.py: reference_name_errors | The shape of every asset:, prompt: and output: name is checked before the queue, and existence is checked later. | tests/test_reference_names.py::TestTheValidationPass::test_a_malformed_reference_is_refused_before_the_queue |
| Library reads | dw/library.py: LibraryPath | Reads go through the roots front to back, so an earlier name shadows a later one. | tests/test_library_path.py::TestResolution::test_the_front_of_the_path_shadows_the_rest |
| Library writes | dw/library.py: LibraryPath | Writes go only to the front root, so saving something opened from a read-only root writes a copy. | tests/test_library_path.py::TestConstruction::test_the_writable_root_comes_first, tests/test_library_sources.py::TestServer::test_saving_an_example_prompt_writes_a_copy |
| LoRA catalog matching | dw/lora_catalog.py: matches, workflow_bases | An entry fits a base only by exact repo id (and H3 partition); no alias or family match. | tests/test_lora_catalog.py::TestMatching::test_the_base_must_match_exactly |
| Hub search | dw/lora_hub.py: search_hub | The Hub is searched only by GET /api/loras/recommend, never raises, and offers no pickle-only repo. | tests/test_lora_hub.py::TestCandidates::test_a_pickle_only_repo_is_dropped, tests/test_lora_hub.py::TestFailure::test_a_hub_error_is_returned_not_raised |
| Packaged builtins | dw/library.py: builtin_root, resolve_sub_workflow_reference | builtin: names the packaged dw/workflows/, not the top-level workflows/ examples. | tests/test_sub_workflow_resolver.py::TestTheResolver::test_a_builtin_resolves_in_the_packaged_root |
| Sub-workflow paths | dw/library.py: resolve_sub_workflow_reference, resolve_sub_workflow | A sub-workflow path is confined to the root it resolves in. The search order is in the docstring of resolve_sub_workflow. | tests/test_sub_workflow_resolver.py::TestTheResolver::test_a_path_escaping_its_root_is_refused |
| Workspace | dw/workspace.py: resolve_workspace, set_workspace | --workspace beats DW_WORKSPACE, which beats the setting, which beats a working directory that looks like a workspace, which beats ~/diffusers-workspace. | tests/test_workspace.py::TestResolution::test_a_flag_wins_over_everything, tests/test_workspace.py::TestResolution::test_a_bare_working_directory_falls_back_to_the_home_workspace |
| Realized workflow | dw/realize.py: realize_workflow, dw/runs.py: write_realized_workflow | Each run directory holds workflow.json, with the run's arguments, seed and stored prompt text pinned. | tests/test_realize.py::TestVariablesAndSeed::test_arguments_become_the_variable_defaults, tests/test_runs.py::TestRealizedWorkflow::test_the_run_directory_holds_a_realized_copy |
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| 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 |
| Run versions | dw/runs.py: open_run, run_versions, record_run_versions | A run takes its number once, when it opens, 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| Overlap windows of a long video | dw/tasks/windows.py: window_video, window_span | Window i covers source frames [i*stride - overlap, i*stride + stride), its synthetic frames repeat the first or last frame, and its audio is cut on the source's own frames_to_samples boundaries, so adjacent windows' strides tile the track with no sample lost or repeated. | tests/test_window_video.py::TestAudio::test_strides_tile_the_source_track_exactly, tests/test_window_video.py::TestRealPath::test_a_path_argument_keeps_its_audio, tests/test_window_video.py::TestFileMatchesInMemory::test_every_window_equals_the_in_memory_window, tests/test_read_frame_range.py |
| Keep a span of a video's frames and audio | dw/tasks/trim.py: trim_video; dw/shots.py: trimmed_shots | Frames [start_frame, start_frame + num_frames) are kept and the audio is cut on frames_to_samples of each end at the track's own rate, so consecutive trims tile the track. A span past the clip's end is refused, never shortened. Shots are clipped to the span, sample side cleared. | tests/test_trim_video.py::TestFramesAndAudio::test_consecutive_trims_tile_the_track, tests/test_trim_video.py::TestShots::test_shots_are_clipped_across_the_boundary |
| Join processed windows back to the source's length | dw/tasks/windows.py: join_windows; dw/task_domains.py: window_count, window_count_problem, join_windows_errors | Output is exactly the source's frames, each once: later windows' first overlap frames blend over the previous window's last on the open ramp dissolve_videos uses. The window count is window_count's ceil(source_frames / stride) and nothing else (it is also window_video's last index plus one). Audio is the source's own track; shots are one per window with overlap_frames on each seam, their sample side laid over that track by dw/shots.py's remeasured_shots (the same rounding as frames_to_samples, so the spans are cumulative). | tests/test_join_windows.py::TestRoundTrip::test_unprocessed_windows_rejoin_to_the_source, tests/test_join_windows.py::TestShots::test_spans_partition_the_frames_and_tile_the_audio, tests/test_join_windows.py::TestUint8Output::test_matches_the_float32_accumulator_exactly |
| A join_windows list of the wrong length, before the run | dw/window_count_errors.py: window_count_errors, wired into validation_errors | Owned by the task, never a template: any join_windows step whose source is probeable header-only (asset:/output: or a readable literal path), with literal num_frames/overlap and an expanded videos list, is checked against window_count_problem - the same rule the run refuses with. Anything not knowable stays silent for the run. | tests/test_window_count_errors.py |
| Fit to a model and restore | dw/tasks/fit.py: fit_to_model, restore_to_source | fit_to_model's record is the whole of what restore_to_source needs: the scale is inferred from the output's size and must be uniform, and restore returns the source's size times that scale and at most its frame count. | tests/test_fit_to_model.py |
| Shared image ops | dw/tasks/image_ops.py: LUMA_WEIGHTS, luma, split_alpha, join_alpha, per_frame | grade, finish and lut take luma (float64 Rec. 709 weights, cast to the input's dtype) and alpha handling from image_ops, never from each other, so an RGBA input comes back RGBA with its alpha untouched; lut.LUMA_WEIGHTS is a re-export. An image command runs over a video or frame list only through per_frame. A media file is read by task._load_media with fetch_image(keep_alpha=True), so a file with transparency arrives RGBA; a pipeline input still flattens to RGB. | tests/test_image_ops.py::TestLuma::test_lut_re_exports_the_one_float64_weights, tests/test_image_ops.py::TestAlpha::test_rgba_round_trip_keeps_the_alpha_bytes, tests/test_image_ops.py::TestOutputsAreByteIdentical::test_every_command_matches_the_pre_refactor_bytes, tests/test_image_ops.py::TestPerFrame::test_a_video_comes_back_as_a_video_with_the_same_frames_and_audio, tests/test_finish.py::TestRgbaFileKeepsAlpha::test_a_file_path_comes_back_rgba_with_its_alpha |
| Audio level of a deliverable | dw/audio_qc.py: warn_without_headroom, warn_if_written_above_full_scale | A muxed video keeps the pre-encode headroom prediction and falls back to it only when the post-write probe cannot measure the file. A result a later step resets the level of (consumed_by_normalizer, dw/step_cache.py) draws neither the post-write warning nor the fallback. | tests/test_result.py::TestNoHeadroom::test_a_clean_video_mux_drops_the_stale_prediction, tests/test_result.py::TestNoHeadroom::test_an_unprobeable_video_mux_falls_back_to_the_prediction, tests/test_result.py::TestNoHeadroom::test_a_video_a_join_level_matches_draws_no_headroom_warning, tests/test_result.py::TestTheWrittenLevel::test_a_file_that_decodes_above_full_scale_warns |
| Level-spread warning on a replaced track | dw/step_cache.py: audio_replaced_downstream, dw/tasks/joins.py: warn_on_level_spread | A join whose track a later pair_audio takes as its video draws no level_spread warning; being that step's audio argument doesn't count. | tests/test_step_cache.py::test_level_spread_warning_suppressed_when_audio_replaced, tests/test_step_cache.py::test_audio_replaced_downstream_false_when_it_is_the_audio_or_unread |
| Template audio-level placement | workflows/templates/minimax/music-video.json, workflows/templates/minimax/music.json | normalize_audio (-3 dBFS) acts only on the track that goes into the final file, so the slices that condition the shots are untouched. music-video slices each shot lead_frames early and trim_video drops the run-up before the join. | — |
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| Validation registry | dw/validation.py: ERROR_CHECKS, WARNING_CHECKS, run_checks | A check is one Check in a registry, and a check that raises becomes one internal finding while the rest still run. | tests/test_validation.py::TestExceptionPolicy::test_a_raising_check_is_one_internal_error_and_the_rest_still_run |
| Step-value checks | dw/step_value_checks.py: fps_errors, null_media_errors, select_errors, chain_prompts_errors | The only caller of these checks is the error registry. | dw/validation.py: ERROR_CHECKS |
| 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 |
| 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 |
| 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. | 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 |
| 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 |
| 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 |
| The estimate | dw/plan.py: estimate, _tempered | plan.estimate quotes the observed figure ahead of the curated one, and blends it toward the curated figure below three runs. | 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 |
| 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 |
| 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. | — |
| 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 |
| 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 |
| 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 |
| 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 and frame count set differently from the template. 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::TestThePlanReportsIt::test_the_estimate_is_inherited_and_the_validate_answer_warns |
| H3 adapter partition | dw/adapter_compatibility.py | An FL2VA LoRA on a reference step is refused, and a LoRA whose file 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| Step cache | dw/step_cache.py, dw/workflow_run.py: cache_lookup | A seeded rerun with unchanged inputs is served from the cache, marked reused: true, and writes nothing; POST /api/memory/clear (dw/server/routes/system.py: clear_memory) drops it. | tests/test_workflow_step_cache.py::test_cache_hit_marks_its_manifest_entry_and_event_reused, tests/test_workflow_step_cache.py::test_second_run_with_unchanged_step_reuses_cached_result |
| No seed, no cache | dw/workflow_run.py: prepare_run | A workflow that sets no seed skips the cache. | tests/test_workflow_step_cache.py::TestCacheHits::test_an_unseeded_workflow_has_no_hits |
| 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 |
| Worker protocol | dw/worker_protocol.py: parse_reply | Every command and reply is a frozen dataclass that travels as a wire dict. | tests/test_worker_messages.py::test_from_wire_inverts_to_wire, tests/test_worker_messages.py::test_an_unknown_reply_type_is_kept_whole_rather_than_raised |
| 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. | — |
| 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 |
| 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 |
| 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 |
| 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 |
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| Opening media | dw/media.py | This is the only module that calls av.open. It imports no torch and no step types. | tests/test_media_layering.py::test_av_open_appears_only_in_media, tests/test_media_layering.py::test_media_imports_no_step_types (no torch: —) |
| 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 |
| 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 |
| 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. 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). 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 |
| 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 |
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| Path validators | dw/security.py: validate_path, validate_workflow_path, validate_output_path | Filesystem access goes through a path validator that is given a base directory. | tests/test_security.py::test_path_validation, .github/codeql/dw-security/DwPathInjection.ql |
| URL and argument validators | dw/security.py: validate_url, sanitize_command_args | A URL must be http or https, and a subprocess argument must not carry a shell metacharacter. | tests/test_security.py::TestValidateUrl::test_dangerous_schemes_are_rejected, tests/test_security.py::TestSanitizeCommandArgs::test_every_shell_metacharacter_is_rejected |
| Locations from a workflow | dw/locations.py | A local path in a workflow's media arguments (named like their media, or declared by the task's @register_command(media_arguments=...), read through TASK_MEDIA_ARGUMENTS) is confined to a known root, a location written as a URL is one security.validate_url accepts, and a URL must not name a host inside the deployment. A host that does not resolve is refused. The requests themselves are dw/outbound.py's. | tests/test_locations.py::TestMediaPathContainment::test_absolute_path_outside_every_root_is_refused, tests/test_locations.py::TestMediaPathContainment::test_a_url_that_is_not_http_is_refused, tests/test_locations.py::TestMediaPathContainment::test_an_upper_case_https_url_is_not_refused_as_another_scheme, tests/test_security_ssrf.py::TestInternalAddressSpellings::test_a_name_that_resolves_inside, tests/test_locations.py::TestTaskMediaArguments::test_an_unreadable_source_is_an_error_at_its_path |
| Outbound requests | dw/outbound.py: safe_get, safe_post | Every outbound request is validated per hop against dw/locations.py's policy, resolved once and dialed at the address the policy checked, capped and timed. No other module under dw/ makes an HTTP request or builds a session or adapter. | tests/test_outbound.py::TestSafeRequest::test_one_lookup_per_hop_and_the_dial_is_the_checked_address |
| Trust gate | dw/trust.py: require_trusted_dotted_name | In an untrusted workflow (the default), a dotted type outside the allowlist is a validation error before anything is imported. | tests/test_security_trust_gate.py::TestValidationRefusesBeforeImport::test_a_dotted_type_is_a_validation_error |
| CodeQL path-injection model | .github/codeql/dw-security/DwPathSanitizers.qll, .github/workflows/codeql.yml | The local pack models the dw/security.py validators (and dw/locations.py's validate_media_path) as sanitizers, so a validator that moves is re-modelled in the same commit. | .github/codeql/dw-security/DwPathInjection.ql |
| Archives never follow links | dw/server/outputs.py: zip_download | A gallery listing drops a symlink that leaves its root, and an archive skips one. | tests/test_security_symlinks.py::TestOutputs::test_the_archive_route_does_not_follow_the_link, tests/test_security_symlinks.py::TestOutputs::test_the_gallery_listing_does_not_enumerate_the_link |
| Engine/server import direction | dw/workspace.py: EXPORTS_SUBDIR | No engine module imports dw.server except the entry point dw/serve.py, and a constant both sides need lives engine-side. | docs/stabilization/baseline.json: import_cycles ratchet (indirect: it fails only on an import that closes a cycle) |
| Module and function size | scripts/arch_metrics.py: SIZE_WARNING, SIZE_CEILING | A module stays at or under 1,100 lines, and it warns above 1,000. A function stays at or under 150 lines. | docs/stabilization/baseline.json: modules_over_size_ceiling, functions_over_150_lines |
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| App factory | dw/server/app.py: create_app | create_app builds the JobManager and app.state, installs the middleware and registers the routes, and all state lives in the JobManager. | — |
| Routers | dw/server/routes/*.py, dw/server/routes/__init__.py: ROUTERS, include_routers, include_file_routes | Routers register in ROUTERS order, because a greedy {name:path} route must come after its specific siblings. The files router comes later, after /mcp. | tests/test_server_downloads.py::test_download_workflow_sets_content_disposition_attachment |
| Job queue | dw/server/jobs.py: JobManager; dw/server/job_results.py: consume_results | A dispatcher thread hands queued jobs, in queue order, to the pool's workers (Worker pool dispatch); each worker runs one job at a time, and consume_results folds that worker's replies into the job, naming files relative to the job's own output_dir. A job carries its own output_dir, asset_dir and workflow_dir, so it stays in its workspace. | tests/test_server_workspaces.py::TestRunning::test_rerun_stays_in_the_workspace_it_ran_in (FIFO: —) |
| Worker pool dispatch | dw/server/jobs.py: JobManager._next_dispatch; dw/server/pool.py: WorkerSlot, check_fits, largest_ceiling_gb; dw/vram_estimate.py: required_vram_gb; dw/server/admission.py: pool_capacity | --devices runs one worker per card; a queued job goes to a free card that fits what it needs, a job that fits no free card keeps its place while a smaller one behind it takes the card, a job bigger than every card is refused at submit, and cancel or a crash touches only the worker running that job. On a backend no cost entry describes, a declared vram_estimate is held at admission to the pool's largest card, so a job the first card cannot hold is not refused when a larger card can hold it. | tests/test_worker_pool.py::TestConcurrency::test_two_workers_run_two_jobs_at_once, tests/test_worker_pool.py::TestBackfill::test_a_job_too_big_for_the_free_card_waits_while_a_smaller_one_takes_it, tests/test_worker_pool.py::TestFitAtSubmit::test_a_job_too_big_for_every_card_is_refused_naming_the_largest, tests/test_worker_pool.py::TestCancel::test_cancel_reaches_the_worker_running_the_job, tests/test_worker_pool.py::TestCrashIsolation::test_a_crashed_worker_fails_only_its_own_job, tests/test_worker_pool.py::TestOomRanking::test_the_later_started_worker_is_ranked_first, tests/test_worker_pool.py::TestFitAtSubmit::test_a_job_only_the_larger_card_holds_is_admitted |
| Card affinity | dw/server/pool.py: choose_slot; dw/server/jobs.py: JobManager.route; dw/worker_protocol.py: workflow_identity | Among the free cards a job fits it goes to the rerun's original card, else the card whose worker last ran its workflow identity (workflow_identity, the one rule the worker caches by too), else one with no worker running, else the first in --devices order; a cache probe and plan.estimate (priced_for) ask about the card route names, and memory is read and cleared per card. | tests/test_worker_pool.py::TestIdentityAffinity::test_a_second_run_lands_on_the_card_that_ran_the_workflow_first, tests/test_worker_pool.py::TestRerunAffinity::test_a_rerun_lands_on_the_original_card_when_it_is_free, tests/test_worker_pool.py::TestProbeRouting::test_the_probe_goes_to_the_worker_the_job_would_be_routed_to, tests/test_worker_pool.py::TestMemoryPerCard::test_a_named_card_running_a_job_is_refused_though_the_other_is_idle |
| Per-card memory and cache | dw/server/worker_memory.py: memory_status, clear_memory, probe_cache | Each card keeps its own last memory reading; an idle card's worker is asked live, a busy one answers with the run's last report and says why it is not live, and a clear leaves a card running a job alone. Every request takes the card's lock with a bounded wait, and a card's lock is never taken while the JobManager's lock is held. | tests/test_worker_pool.py::TestMemoryPerCard::test_a_named_card_running_a_job_is_refused_though_the_other_is_idle, tests/test_worker_pool.py::TestProbeRouting::test_the_probe_goes_to_the_worker_the_job_would_be_routed_to, tests/test_server.py::test_memory_says_why_a_reading_is_not_the_worker_s |
| 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 |
| Job history | dw/server/job_history.py: JobHistory | Finished jobs persist in jobs.sqlite, in WAL mode, so the Jobs view survives a restart. | tests/test_server.py::test_job_history_survives_restart_and_reruns, tests/test_job_history_wal.py::test_the_jobs_database_uses_wal_mode |
| 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 |
| 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 |
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| Inline images | dw/server/inline_media.py | Fitting an image to a longest side and halving it under a base64 budget happens on the server, for /image and /frames alike; dw_mcp forwards the size and budget and imports no Pillow. | tests/test_server_gallery_image.py, tests/test_mcp_server.py::TestStartupWeight::test_the_server_starts_without_importing_the_engine |
| Workflow patch | dw/library.py: merge_patch; dw/server/routes/library.py: patch_workflow | A merge patch is applied on the server under the lock PUT takes; no client reads, merges and writes back. | tests/test_server_library_path.py::TestPatchWorkflow::test_patch_merges_onto_the_stored_definition |
| Deleting a job's run | dw/server/jobs.py: JobManager.run_location; dw/server/outputs.py: delete_run_directory | The server resolves a job's run directory against the root the job ran in, and refuses a job still queued or running. | tests/test_server_jobs.py::TestDeleteAJobsRun::test_a_running_job_is_409 |
| Level findings | dw/server/assess.py: level_findings | Gallery metadata reports level problems from dw/audio_qc.py's thresholds; no client restates a threshold. | tests/test_server_assess.py::TestMetadataLevelFindings::test_level_findings_read_audio_qc_thresholds |
| API errors | dw_mcp/client.py | An API failure becomes a message a person can act on, here and nowhere else. | tests/test_mcp_client.py::test_a_400_surfaces_the_servers_detail_verbatim |
| Concept | Owner | Rule | Enforced by |
|---|---|---|---|
| The UI reads engine fields | ui/src/lib/plan.ts: describePlan, ui/src/lib/results.ts: sectionBySubfolder | The UI reads plan, version and subfolder as fields the server sends and derives nothing of its own, and it never sends acknowledged_cost. | ui/src/lib/plan.test.ts, ui/src/lib/results.test.ts |
| Reference prefixes in the UI | ui/src/lib/references.ts | The only module in ui/src that spells a reference prefix; each equals dw/references.py's. | tests/test_ui_twins.py::test_the_ui_spells_every_reference_prefix_the_engine_does; prefix_literals in ui/scripts/arch-metrics.mjs |
| Output kinds on the job page | dw/server/outputs.py: MEDIA_KINDS, output_kinds | The page renders an output by the output_kinds the job detail carries, never by its extension. | tests/test_server.py::test_a_job_reports_each_output_files_media_kind, ui/src/lib/pages/JobPage.test.ts |
| The editor's live reference check | ui/src/lib/flow.ts: danglingReferenceDetails, owned by dw/previous_results.py and dw/for_each.py | The editor warns as the author types, so it keeps a copy of the reference rules; one case file is run through both, the engine deciding each case. | tests/test_ui_twins.py::test_the_engine_decides_each_shared_reference_case, ui/src/lib/flow.test.ts |
| Name segments in the UI | ui/src/lib/names.ts: isNameSegment | Workspaces, folders and stored names follow dw/security.py's WORKSPACE_NAME_PATTERN and length cap, counted in code points. | tests/test_ui_twins.py::test_the_engine_decides_each_shared_workspace_name_case, ui/src/lib/names.test.ts |
| UI copies of engine rules | the constants tests/test_ui_twins.py reads | A list the UI must hold equals its owner, read from the TS source; a rule tested on both sides reads one case file in tests/fixtures/. | tests/test_ui_twins.py |
| UI overlays and suggestions | ui/src/lib/ui/: ConfirmDialog, Modal, Popover, Suggest | Bits UI is imported only here; pages and components use the wrappers, which own focus, Escape, outside presses and scroll lock. Overlay styles and the stacking scale (--layer-*) live in ui/src/app.css. | ui/eslint.config.js (no-restricted-imports), ui/src/lib/ui/*.test.ts, ui/e2e/chrome.spec.ts |
| Escape on a page under an overlay | ui/src/lib/ui/layers.svelte.ts: holdLayer, overlayOpen | Every open overlay holds a layer; a page's own Escape handling acts only when none is open. | ui/src/lib/pages/GalleryPage.test.ts (an Escape that closes a confirm leaves the selection) |
| The editors' document | ui/src/lib/editorShell.svelte.ts: DocumentEditor | The workflow and prompt editors keep one rule each for the view (remembered per editor), the JSON draft (a failed parse pins it), dirty against the last load or save, the save path, and the tab-close guard. | ui/src/lib/editorShell.test.ts, ui/src/lib/pages/PromptEditorPage.test.ts, ui/src/lib/pages/EditorPage.test.ts |
| UI polling | ui/src/lib/poll.ts: poll, sleep | A page that refreshes on a timer starts it through poll and stops it with the function poll returns. | ui/src/lib/poll.test.ts |
| Workspace state in the UI | ui/src/lib/workspaceState.svelte.ts: workspace | The current workspace is one $state; api.ts reads it from here, so the request layer imports no page state. | import_cycles in ui/scripts/arch-metrics.mjs |
| The UI's response contract | dw/server/api_models.py: ApiModel, send_rejected_responses; scripts/dump_openapi.py | Every JSON route api.ts calls declares a response model, and types.ts re-exports the types generated from it (ui/src/lib/generated/). The payload does not change: an absent key stays absent (response_model_exclude_unset), a sometimes-sent key is sometimes(). Runtime is lenient - an undeclared key passes and a rejected response is logged and sent as built; tests, the e2e server and the dump run strict (DW_STRICT_RESPONSES=1). The document is generated under the FastAPI and Pydantic constraints-openapi.txt pins: CI installs them, and the dump refuses to write under others. | tests/test_api_contract.py, tests/test_ui_twins.py::test_every_json_route_the_ui_calls_declares_its_response, CI's "Response contract" step |
| Where --live appears | ui/src/app.css (its header) | The state colour marks machine state only, in the files ui/scripts/design-rules.test.ts lists. | ui/scripts/design-rules.test.ts |
| UI architecture ratchet | ui/scripts/arch-metrics.mjs | No metric rises above docs/stabilization/ui/baseline.json. | the ui job in .github/workflows/ci.yml; npm run preflight |
| Back | FazBrowse Home | New Git URL |