Nodes/CMK Flow/CMK Boundary Cache
ComfyUI Node

CMK Boundary Cache

Why the second pass doesn't run twice

By CMKFlow·Created 3 months ago·Updated a day ago· 6
CMK Boundary Cache
  • MODEL
  • IMAGE_1ST_PASS
  • IMAGE_REFINED
  • LOG
  • MODEL
  • IMAGE 1ST PASS
  • IMAGE REFINED
  • LOG

Four sockets in, the same four out: MODEL, IMAGE_1ST_PASS, IMAGE_REFINED, LOG. Nothing about it looks like it does anything. It is, in fact, the reason your refiner doesn't run three times for one image.

Start with the problem. A refiner produces two images - the first pass and the refined result - and several things downstream want them: the comparison view, the before/after Visualizer stage, the output branch, maybe a save node. In a plain ComfyUI graph, every consumer wired to the sampler output is a separate evaluation request, and the pack's rules say no preview or output branch should be able to reach the refiner execute node directly. So there has to be one place where the refiner's output is materialised and everything else taps that. This node is that place: a mandatory materialisation boundary.

How the cache decides

On execution it builds a fingerprint of the branch and uses that as a cache key. The fingerprint isn't a hash of the images - it's a hash of the graph behind the two image inputs, resolved recursively through the expanded prompt: the node that produced IMAGE_1ST_PASS, the node that produced IMAGE_REFINED, and the parameters feeding them. Change the refiner seed, a step count, a prompt, the model, anything upstream - new fingerprint, new key, new work. Change nothing, and you hit.

Entries live on disk under ComfyUI's temp folder, in temp/cmk/refiner_boundary/, as a refiner_<hash>.safetensors plus a .json companion. There's a hard ceiling of sixteen entries, an index tracking the latest revision per boundary node so a re-run replaces rather than accumulates, and a last_status.json file. The console prints what happened:

[CMK Refiner Boundary Cache] MISS 4f2a9c1e77b0 -> BOTH IMAGES STORED
[CMK Refiner Boundary Cache] HIT 4f2a9c1e77b0 -> BOTH IMAGES/LOG

Because it's on disk and not just in memory, this one can hit across a ComfyUI restart - unlike the pack's general image boundaries, which are cleared when the session ends. A restart hit still needs the current MODEL pipe present; if it isn't, the node raises a clear restart hit requires current MODEL error rather than handing you a stale model reference.

If the fingerprint can't be built - the boundary node isn't found in the expanded prompt, or the image inputs aren't proper graph links - it doesn't cache and doesn't fail. It logs BYPASS_NO_FINGERPRINT and passes the values through. Same for a failed write: STORE_FAILED, images still returned. Cache problems are never fatal here, which is the right call for something whose whole job is speed.

If it seems broken

Read temp/cmk/refiner_boundary/last_status.json. It records the last outcome - HIT, MISS_STORED, NO_FINGERPRINT, HIT_FAILED, STORE_FAILED - plus the cache key and a short detail string. That file answers "why did this re-run" in one look, and it's far better than guessing from timing. HIT_FAILED means a corrupt or unreadable entry; the node rebuilds, so it's self-healing and usually only costs you one run.

The HIT is also stricter than people expect in one direction: a cache hit only counts if the dependency manifest matches the branch revisions actually materialised. Nudge one branch and its cached siblings still hit while the boundary re-materialises - which is exactly the behaviour you want, and also why "it re-ran everything" is rarely what happened. Check last_status.json before you clear caches.

A naming trap before you install anything

Five different boundary cache classes in this pack share the display title CMK Boundary Cache - detailer, face, FaceRebuild, FaceSwap, and this refiner one. They are not interchangeable: different input counts, cache contracts and cache directories. When you're hunting one down in a workflow, read the node's class, not the title in the header.

Installing the pack

Manager → search CMK Flow → install the CMKFlow entry → restart. Manually, from the ComfyUI root:

git clone https://github.com/CMKFlow/cmk_nodes.git custom_nodes/cmk_nodes
python3 custom_nodes/cmk_nodes/scripts/install_cmk_requirements.py

Wait for CMK dependency check: OK. The installer determines which Python interpreter ComfyUI is really using - Desktop setups often have three candidates - and installs requirements.txt into that one; it then verifies every mandatory import, which matters because the pack imports all its nodes as one graph and a failed import can remove nodes well away from the offending library. A git clone never runs pip by itself, so this command is part of both install and update:

git -C custom_nodes/cmk_nodes pull --ff-only
python3 custom_nodes/cmk_nodes/scripts/install_cmk_requirements.py

The pack requires Vue Nodes / Nodes 2.0 in ComfyUI settings, and Execution → Live preview method: auto if you want live previews during sampler and refiner runs. This node is CMK/Developer/ - internal plumbing, findable by search, absent from the Flow Browser.

One standing caveat from the pack's own documentation, worth repeating because it's easy to over-trust: caches are temporary accelerators, not a portable project format. Don't ship a .safetensors from temp/cmk/ to a friend and expect it to resolve.

CategoryCMK/Internal/Boundary & Cache

Inputs (4)

NameTypeDefaultDescription
MODELCMK_MODEL_PIPE—
IMAGE_1ST_PASSIMAGE—
IMAGE_REFINEDIMAGE—
LOGCMK_LOG_PIPE—

Outputs (4)

NameTypeDescription
MODELCMK_MODEL_PIPE—
IMAGE 1ST PASSIMAGE—
IMAGE REFINEDIMAGE—
LOGCMK_LOG_PIPE—