CMK Boundary Cache
Stop re-running the Z-Image decode every time you tweak the post-process
- MODEL
- IMAGE
- LOG
- diagnostic
- MODEL
- IMAGE
- LOG
- diagnostic
There are four nodes in CMK Flow called "CMK Boundary Cache", which is a naming decision I'll leave alone. This one is the Z-Image Turbo variant - on canvas it's the boundary that closes the ZIT generation path and hands a decoded image to the family-neutral post-process zone.
Why it exists comes down to how people actually iterate on Z-Image. Turbo runs in a handful of steps, so the sampler is not the expensive part; the expensive part is everything after it - VAE decode, then the detailer, face passes, upscaling, each of which you'll tweak fifteen times in an hour. Without a boundary, changing anything downstream makes ComfyUI walk back up the chain and re-execute what it can't prove is unchanged. The boundary's job is to prove it.
How it works
The node keeps a session dictionary (_Z_IMAGE_SESSION) mapping a cache key to a (model_pipe, diagnostic) pair, plus disk artifacts under the pack's cache root:
ComfyUI/temp/cmk/
The flow is driven by lazy evaluation:
check_lazy_statuscomputes the key from the node's own identity and schema version (cmk_z_image_boundary_v2), then checks whether the key is in the session dict and the matching disk files exist. If both are true it logsHIT_READYand returns an empty list - it requests none of its inputs. The sampler upstream is never evaluated.- On the real run it re-checks. A hit loads the stored image and log from disk, pulls the model and diagnostic from the session dict and returns them, logging
HIT. - A miss requires all four inputs; if any is missing it raises rather than guessing. Then it writes the image and log to disk, stores the model and diagnostic in the session, prints
MISS → STOREDand writes a status record. If the disk write fails you'll seeSTORE_FAILED, and the node still returns the live values, so a caching problem doesn't kill the run.
Two rules from the pack's architecture doc that you can see enforced here: the fingerprint is built from compact, module-specific information rather than a recursive serialisation of the whole upstream graph, and a HIT is only accepted when the dependency manifest still matches the materialised state. That's what keeps this from being an exponential traversal - a real failure mode in graph-level caching.
The honest scope: this is a session cache. A ComfyUI restart clears the image boundary caches. Only the pack's video segmentation has a deliberate cross-session continuation contract. And it's an accelerator, not a project format - don't build a workflow that depends on temp/cmk/ surviving.
Inputs and outputs
All four inputs are required and all four are lazy, which is the mechanism letting the node skip the whole upstream request:
MODEL(CMK_MODEL_PIPE) - the ZIT model context.IMAGE- the decoded image.LOG(CMK_LOG_PIPE) - documentary; cached with the image so the log and the image belong together.diagnostic(CMK_DIAGNOSTIC) - cached alongside.
Outputs are the same four, in the same order: MODEL, IMAGE, LOG, diagnostic. Wire IMAGEonward into the post-process modules andMODEL` into whatever needs the family context.
Strict input typing is deliberate: if MODEL or LOG isn't a CMK pipe dictionary, the node raises a type error rather than passing nonsense. Mis-wiring a ZIT boundary is caught at the boundary, not three modules later.
Install
It's a CMK/Developer/Boundary & Cache node - infrastructure that arrives with the pack. Manager → search CMK Flow → install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/CMKFlow/cmk_nodes
python3 custom_nodes/cmk_nodes/scripts/install_cmk_requirements.py
python3 custom_nodes/cmk_nodes/scripts/check_cmk_resources.py --models-root "/path/to/shared/models"
The ZIT path is the one that makes the resource check worth running: z_image_turbo_bf16.safetensors, the qwen_3_4b text encoder and ae.safetensors are multiple gigabytes, and the checker will name them individually rather than just declaring your models folder non-empty.
Common issues
MISS → STOREDon the first run after a restart. Expected, always. The interesting question is whether the second run saysHIT.- Never hits. Something upstream produces a new object identity each run - a random seed, or one of those ComfyUI nodes that returns
float("NaN")fromIS_CHANGEDand is therefore permanently dirty. One of those in the chain defeats caching for everything behind it. - "cache miss requires MODEL, IMAGE, …" You wired the node but a required input is absent - usually the diagnostic tail of the ZIT path. The message names exactly which.
- Stale image after editing the generation settings. The key covers the node's identity and schema plus the materialised dependency state. If you changed something the fingerprint doesn't include, restart ComfyUI to be certain rather than trusting the panel.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| MODEL | CMK_MODEL_PIPE | — | |
| IMAGE | IMAGE | — | |
| LOG | CMK_LOG_PIPE | — | |
| diagnostic | CMK_DIAGNOSTIC | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| MODEL | CMK_MODEL_PIPE | — |
| IMAGE | IMAGE | — |
| LOG | CMK_LOG_PIPE | — |
| diagnostic | CMK_DIAGNOSTIC | — |