Both qwen-zimage stages prompt with module constants, and at CFG 1.0 DiffSynth's PipelineUnitRunner reuses the positive embedding for the negative side rather than encoding it, so exactly one embedding per stage is ever computed. Persist it and neither text encoder has to be loaded at all. Measured on an H100 volume: this drops 15.45 GiB (Qwen2.5-VL) and 7.49 GiB (Z-Image) of an 87.6 GiB per-request read, worth a median 11.76 s and 4.10 s of load time paired within five containers. A nine-face fixture returned sha256 c8567e11077de32a both with and without the cache, so the output is byte-identical and the provider-oracle clearance is untouched. The cache key carries the cache version, model id, pipeline output params and the exact prompt, so a model bump or a prompt edit recomputes instead of reading a stale embedding. The write is atomic because a torn file must never read back as a hit, and a miss after the text encoder was already dropped raises rather than calling a model that is not loaded. _model_cache_dir now prefers HF_HOME: on a scale-to-zero runner that is the only persistently mounted path, so anything below it is re-derived every request. The YuNet download follows the same root. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1.8 KiB
globs, description
| globs | description | |||||||
|---|---|---|---|---|---|---|---|---|
|
Command contracts, project gate, typing boundaries, and model-adjacent test invariants. |
Development invariants
Command contracts
Every single-image command declares source with dir_okay=False; batch declares its directory with file_okay=False. Keep tests/test_cli_robustness.py::TestDirectoryInputIsRejected as the regression guard.
Exit-code and no-signal behavior is a public contract. Read the command-line section of ../../docs/module-internals.md before changing it.
Local gate
Run bash maintain.sh from the repository root. The authoritative type gate is scoped to src/; full-project Pyright can exhaust Node memory on the ML dependency graph.
Boundary modules for cv2, Torch, and Diffusers may carry narrow per-file relaxations for unknown third-party types. Keep pure-logic files strict, preserve the local piexif stub, and fix real errors before widening a pragma.
Model-adjacent tests
Do not classify an entire module as untestable because its main path downloads a model. Keep pure behavior covered without downloads, including:
- target-size selection in
test_invisible_engine.py; - unsharp and adaptive-polish helpers in
test_humanizer.py; - mocked device fallback in
test_img2img_runner.py; - tiling geometry and blending in
test_tiling.py; - prompt-embedding cache keying, storage round-trip, and the cross-pipeline reuse
that lets a stack load without its text encoder, in
test_qwen_zimage_pipeline.py.
Use availability checks only for paths that actually load large models.
Environment setup, dependency recovery, CI behavior, and fixture policy: ../../docs/development.md.