Release v0.13.0-alpha: LoRA support, Depth ControlNet, and two broken presets fixed - #84
Merged
Conversation
Both sketch-to-image presets fed ControlNet a pure-black control image for light-on-dark art and solid filled shapes: LineartStandardPreprocessor and ScribblePreprocessor each returned max=0, 0% ink on such a source. ControlNet had no signal, so the preset degraded to plain text-to-image and the user just saw their sketch ignored -- with no error anywhere. Measured live against ComfyUI on a 1024px filled silhouette: Scribble_PiDiNet_Preprocessor 3.18% ink AnyLineArtPreprocessor_aux 1.14% ink CannyEdgePreprocessor 0.24% ink ScribblePreprocessor 0.00% ink (dead) LineartStandardPreprocessor 0.00% ink (dead) The learned edge detectors are polarity-robust; the naive ones assume dark strokes on white paper. So: - sketch2img-linecn-basic switches to AnyLineArtPreprocessor_aux, keeping its existing LineArt ControlNet. This is a bug fix to a preset that shipped "stable" while being broken for that whole class of input. - New sketch2img-scribble-basic preset on Scribble_PiDiNet_Preprocessor and the Scribble ControlNet, for loose gestural strokes where LineArt holds the drawn line too tightly. Its ControlNet model was already installed; no new custom node package. Both preprocessors now run at 1024 rather than the hardcoded 512, which was discarding line detail before ControlNet ever saw it. Both new node classes are registered in CUSTOM_NODE_PACKAGES, without which Setup and Workflow Health would stop telling users they need controlnet_aux. LineartStandardPreprocessor stays mapped there for users' own custom workflows. Verified end-to-end against ComfyUI: both presets submitted with the reporting user's seed and prompt now compose to the sketch silhouette. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two defects kept txt2img-flux2-dev-gguf from working at all. The Model dropdown was empty of .gguf files because the preset shared DIFFUSION_MODEL_SOURCE, which asks UNETLoader for its file list. Core UNETLoader does not enumerate .gguf at all -- comfyClient already documented this for the inventory buckets, but the preset dropdown asks preset.modelSource directly and never got the same treatment. A preset built on UnetLoaderGGUF now points at that loader instead, so the model sitting in models/diffusion_models/ is visible where it belongs. Generation then failed on the preset that has no negative conditioning node. The txt2img/img2img/sketch builders injected negativePrompt with required=true, which throws when a preset has no such target -- and Flux.2 deliberately has none, being guidance-distilled. buildInpaint already passed it non-required for exactly this reason (Flux Fill); the other three now match, so a preset without a negative prompt no longer crashes on Generate. Verified against the live ComfyUI: /object_info/UnetLoaderGGUF lists flux2-dev-Q4_K_M.gguf, and the preset generates end to end. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
LineArt and Scribble both hold the drawn stroke. Neither carries depth, so nothing in the panel could match a generated element to the camera angle of an existing composite -- the thing artists actually reach for ControlNet to do when compositing into a scene. sketch2img-depth-basic is the third variant of a graph shape the registry already documents as deliberately shared: the node ids match LineArt and Scribble exactly, and only the preprocessor and the ControlNet it feeds differ. controlStrength was already an injection name, so no new injection type was needed. DepthAnythingV2Preprocessor comes from comfyui_controlnet_aux, which was already the sole entry in CUSTOM_NODE_PACKAGES for the existing sketch presets -- the frozen custom-node inventory test passes unchanged, so this adds no new node dependency. The workflow pins ckpt_name and resolution explicitly rather than relying on the node pack's defaults, so a run stays reproducible across pack updates. The ControlNet weight is new: control_v11f1p_sd15_depth_fp16 from the same comfyanonymous repo the lineart and scribble weights come from, its size verified by HEAD request at 722601100 bytes -- byte-identical to its three siblings already in the registry. Verified against the live ComfyUI: all ten node classes resolve, and the source/API equivalence check covers the new pair rather than skipping it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The verified-machine spec said ComfyUI 0.27.1; the running instance reports 0.30.0. A research agent judging what will run on this hardware was reasoning from a version two minors stale. Python 3.10.11 and PyTorch 2.6.0+cu124 were re-checked against /system_stats and are unchanged, so only the one number moves. The "ver": "0.27.1" strings in src/workflows/source/*.json are litegraph provenance stamps recording which version authored each node, not a statement about this machine, and are deliberately left alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eleven LoRAs sat on the reference machine that the panel could not use. getLoraNames() has been in comfyClient since before this change and was never called by anything. A LoRA cannot be injected the way every other control is. Core LoraLoader has no "none" entry -- lora_name is a combo of files that exist -- so a permanently wired loader would force everyone to own and load one. The node is therefore absent from the shipped workflow and spliced in only when an artist picks a LoRA, rewiring the sampler's model input and both text encodes' clip inputs. This is the first time building a workflow changes its topology rather than its values, so the wiring is declared per preset rather than inferred: guessing which MODEL and CLIP edges are the main ones would, when wrong, produce an image with the LoRA applied to nothing and no error to explain it. Choosing nothing leaves the graph byte-identical to what ships. Both text encodes are rewired, not just the positive one. At CFG 1 the negative contributes nothing, but leaving it on the bare CLIP would put two different text encoders in one graph -- harmless now and a confusing bug the first time this preset runs above CFG 1. The dropdown is labelled, not filtered. ComfyUI serves only a LoRA's name, size and timestamps, so the panel cannot inspect a file it offers; the metadata that would answer the question is not served and lies when read anyway -- illustration.safetensors and meat_v1.safetensors both declare ss_base_model_version sd_1.5 while their tensor keys are Flux. Filename hints therefore label entries and sort likely matches first, but never hide one: a strict filter keyed on any available signal would hide working LoRAs and still admit broken ones. The hint never claims a match it cannot support, which is the asymmetry the tests pin down -- over-claiming sends the artist hunting a bug in the wrong place, while a missed mismatch only costs a generation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Selecting None on the Krea-2 preset failed the whole generation with HTTP 400 prompt_outputs_failed_validation, while selecting an actual LoRA worked -- the opposite of what a broken splice would do, which is what pointed at the UI rather than the builder. Both built workflows were confirmed valid by submitting them to a live ComfyUI directly. readSelectValue falls back to an option's label when its value is empty, because UXP selects do not always report `.value`. Every other dropdown in the panel is unaffected: their values and labels are the same string. The LoRA list introduced the first option where they differ, so an empty-valued "None" came back as the literal text "None", which read as a real choice -- the strength field appeared under a None selection, visible in the screenshot that reported this, and the splice then asked ComfyUI to load a file called None. The None entry now carries a sentinel that is neither empty nor a plausible filename, so the label fallback has nothing to do. Selection handling moves into a pure resolveLoraSelection so the case can be pinned by tests rather than only in the panel: None, the sentinel, the bare label, empty and whitespace all resolve to no LoRA, and a strength of 0 stays 0 rather than being swallowed as falsy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
LoRA support shipped on Krea-2 Turbo alone, which left the feature half
present: the control appeared for one entry in the Workflow list and
silently vanished for the rest.
The four remaining text-to-image presets now declare an insertion point.
The wiring was derived from each shipped workflow rather than assumed,
and the three shapes differ in ways that matter:
- txt2img-basic and flux1-dev-fp8 load from a checkpoint, which is its
own CLIP source -- MODEL on slot 0, CLIP on slot 1 of one node,
where a diffusion-model stack has two separate loaders. The
insertion already carried a slot, so both shapes splice unchanged.
- z-image-turbo's model consumer is ModelSamplingAuraFlow, not the
sampler. A LoRA has to apply before the sampling-mode wrapper;
rewiring the sampler instead would have bypassed the wrapper and
quietly changed how the model is sampled.
- flux2-dev-gguf has one clip consumer, not two, having no negative
conditioning node, and its model consumer is BasicGuider.
Each insertion is now checked by a test that runs per preset: the node
id is unused by that workflow, every declared source and consumer
exists, and nothing downstream is left reading the bare model or CLIP --
the silent failure where a LoRA loads and applies to nothing.
All five spliced graphs were confirmed against the live ComfyUI by
submitting them to /prompt, not only by unit test.
Also bundles the flux2-dev-gguf workflow into WORKFLOW_TEMPLATES. Every
other runnable preset was already imported there; that one was left to a
runtime fetch, which worked in the panel but made the preset unbuildable
under test.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Completes the rollout: all eleven presets that load a model and a text encoder now take an optional LoRA, leaving only inpaint, outpaint and upscale without one, which is deliberate. The three sketch presets share a graph shape the registry already treats as deliberately identical -- only the preprocessor and ControlNet differ between them, and neither touches the model or CLIP path -- so they share one insertion built by a helper rather than three copies that could drift apart. The panel's LoRA logic now takes a control group instead of reading fixed element names, because the same row exists on three tool cards and the alternative was the same six-element signature repeated at every call site. One ordering bug was caught and fixed while writing this: the Krea-2 img2img insertion was declared above the node map it reads, which is a temporal dead zone error at module load that tsc does not report. It now sits below its map, and the per-preset tests would have caught it on the next run regardless. All eleven spliced graphs were confirmed valid by submitting them to the live ComfyUI, with a real uploaded source image so the six image-input presets exercised their LoadImage node rather than failing on a placeholder filename. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Written before any code, because the feature touches result handling and the preview panel's URL ownership, and a mistake there affects every tool rather than only this feature. Two findings changed the shape of it. batch_size is already present on the empty-latent node of eight shipped workflows, so batching those is an ordinary value injection with no graph surgery -- only the three img2img presets need a RepeatLatentBatch splice, because they build their latent from the captured layer with VAEEncode. And the generation controller's one-run invariant is not threatened by this at all, which had been assumed. A batch is one prompt, one prompt id, one run; the controller gates on which run is current and never inspects the result's shape, and runPipeline is already generic in it. What actually breaks is narrower: the single-result type, the preview panel's two owned URL slots, and what Import means when there are four images. The last of those is a product question and is left open. Four decisions are called out for Mehran rather than guessed, and the work is staged so the retrieval half can be built before they land. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bumped early so the panel footer reads the new version during the release smoke test rather than after it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Written from git log against the v0.12.0 tag and the code, not from a task list, per the lesson from v0.8.0: a draft written from tasks described a fix a later commit had replaced. Two entries are deliberately absent. The "None" LoRA defect was introduced and fixed inside this release, so it never reached a user and is not a fix worth reporting; and the sketch preprocessor fix predates this session's work on the branch but was never released, so it belongs here rather than being assumed shipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replaces the alpha checkpoint line, the "New in" list, the tester focus and the version-stamped zip and plugin names. The one remaining v0.12.0 mention is deliberate: it names the release the Flux.2 defects shipped in, which is the point of that line. The tester focus leads with the LoRA paths because they are the release's new surface, and includes the mismatched-LoRA case explicitly -- a generation that succeeds with a visibly unchanged image is the expected behaviour there, and a tester who is not told that will file it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nine version references, plus three claims that stopped being true. "LoRA browser" was listed as future work; LoRAs ship in this release, so the page would have been advertising a shipped feature as unbuilt. The Sketch to Image line named LINECN and one ControlNet model as the only option, where there are now three presets each needing their own. And a new boundary is added for the one real limitation of the LoRA work: the list cannot be filtered by compatibility, because ComfyUI does not report it, so a mismatched LoRA fails silently. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ships optional LoRA support, a Depth ControlNet sketch preset, and fixes for two presets that were quietly broken in v0.12.0.
What's in it
Optional LoRA on eleven presets — every preset that loads a model and a text encoder, across Text to Image, Image to Image and Sketch to Image. Choosing nothing leaves the shipped workflow byte-identical, because ComfyUI's
LoraLoaderhas no "none" entry: the node is spliced into the graph only when a LoRA is actually picked, and the model and text-encode inputs downstream are rewired to it. This is the first time building a workflow changes its shape rather than its values, so each preset declares its own wiring rather than having it inferred. Three genuinely different shapes turned up among the eleven, including Z-Image, where the LoRA must be applied beforeModelSamplingAuraFlowrather than at the sampler — rewiring the sampler there would have bypassed the wrapper and changed how the model is sampled, with no error.A Depth ControlNet sketch preset, holding scene perspective where LineArt and Scribble hold the drawn stroke. Needs one new ControlNet weight; no new node package, since the depth estimator comes from
comfyui_controlnet_auxwhich the sketch presets already required.Two fixes for presets that failed silently. Sketch to Image fed ControlNet a blank control image for light-on-dark art, so the sketch was ignored with nothing reported. The Flux.2 dev (GGUF) preset that headlined v0.12.0 could not be run at all: its Model dropdown asked core
UNETLoaderfor the file list, and that loader does not enumerate.gguffiles, and pressing Generate then failed because the builder required a negative-prompt target on a preset that deliberately has none.Verification
LoadImagenode rather than a placeholder.Notes for review
1105811(the sketch preprocessor fix and the Scribble preset) predates this branch's release work but had never been released, so it is included in the v0.13.0 notes rather than assumed shipped.docs/BATCH_GENERATION.mdis a design note only. No batch code is in this PR.🤖 Generated with Claude Code