From a571e0ec7ceb9dee8b9522fb770a416663d19e4a Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 21 Aug 2026 01:58:11 +0300 Subject: [PATCH] fix(studio): say when a wired conditioning is being ignored CLIP wins whenever it is connected and the wired CONDITIONING is never read; the ownership label that knew this was computed and thrown away. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 6 ++++ conditioning.py | 12 +++++++ tests/test_minimax_h3_studio.py | 57 +++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e34ac188..867c02d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,12 @@ quietly. Latent width and height snap to even, since a patchified model cannot take odd. ### Fixed +- **Studio said nothing when both CLIP and a positive CONDITIONING were wired to it.** CLIP + wins and the wired conditioning is never read — but the ownership label that knew this was + computed and discarded, so a graph feeding Studio from an i2v node looked like it was + working while the prompt path quietly supplied everything. Now stated once per run and + carried in the encode status. + - **The late-step gate every rating-driven mechanism shares was measuring the wrong thing on H3**, so embed guidance, score slider, DynaShift and output guidance were inert or nearly inert while reporting themselves active. `max(0, 1 - 2*sigma)` reads sigma as diff --git a/conditioning.py b/conditioning.py index 8efe2e28..38eac0e5 100644 --- a/conditioning.py +++ b/conditioning.py @@ -7048,6 +7048,18 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): clip, prompt_text, encode_cache=encode_cache, reference_image=reference_image, h3_references=h3_references, ) + if positive_conditioning is not None: + # Both connected: CLIP wins and the wired CONDITIONING is never read. Silent + # until now — the ownership label below was computed and thrown away — so a + # graph feeding Studio from an i2v node looked like it was working while the + # prompt path quietly supplied everything. + note = ("both CLIP and positive CONDITIONING are connected — CLIP owns the " + "prompt and the wired CONDITIONING is IGNORED; disconnect CLIP to " + "use the wired one") + if not getattr(self, "_funpack_cond_owner_noted", False): + self._funpack_cond_owner_noted = True + print(f"[FunPackStudio] {note}") + encode_status = f"{encode_status}; {note}" return cond, meta, encode_status, "CLIP-owned" if positive_conditioning is None: diff --git a/tests/test_minimax_h3_studio.py b/tests/test_minimax_h3_studio.py index 91257ea7..48ca283b 100644 --- a/tests/test_minimax_h3_studio.py +++ b/tests/test_minimax_h3_studio.py @@ -156,3 +156,60 @@ def test_an_ltx_split_is_left_alone(): scenes = node._v2_transition_scene_conditionings(LTXClip(), ["a room", "a street"], reference_image=IMAGE) assert all("funpack_h3_anchor" not in m for _c, m in scenes) + + +# --- which input actually owns the conditioning ----------------------------------- +# CLIP wins whenever it is connected; a wired positive CONDITIONING is then never read. +# That was silent (the ownership label was computed and discarded), so a graph feeding +# Studio from an i2v node looked like it was steering conditioning it never saw. + +class _StubClip: + pass + + +def _source(node, clip, wired, monkeypatch): + monkeypatch.setattr( + node, "_v2_encode_prompt", + lambda *a, **k: (torch.ones(1, 4, 8), {"pooled_output": None}, "encoded"), + raising=False) + monkeypatch.setattr( + node, "_v2_extract_conditioning", + lambda c: (torch.zeros(1, 4, 8), {"pooled_output": None}), raising=False) + monkeypatch.setattr(node, "_v2_text_tokenizer_status", lambda: "tokenizer ok", raising=False) + return node._v2_conditioning_source(clip, "a prompt", wired) + + +def test_clip_owns_the_conditioning_when_both_are_connected(monkeypatch, capsys): + node = FunPackVideoRefinerV2() + wired = [[torch.zeros(1, 4, 8), {}]] + cond, _meta, status, owner = _source(node, _StubClip(), wired, monkeypatch) + assert owner == "CLIP-owned" + assert torch.equal(cond, torch.ones(1, 4, 8)) # the wired tensor was never used + assert "IGNORED" in status + assert "IGNORED" in capsys.readouterr().out + + +def test_the_both_connected_warning_is_said_once_not_once_per_scene(monkeypatch, capsys): + node = FunPackVideoRefinerV2() + wired = [[torch.zeros(1, 4, 8), {}]] + for _ in range(3): + _source(node, _StubClip(), wired, monkeypatch) + assert capsys.readouterr().out.count("IGNORED") == 1 + + +def test_a_wired_conditioning_is_used_when_clip_is_absent(monkeypatch, capsys): + node = FunPackVideoRefinerV2() + wired = [[torch.zeros(1, 4, 8), {}]] + cond, _meta, status, owner = _source(node, None, wired, monkeypatch) + assert owner == "CONDITIONING-owned" + assert torch.equal(cond, torch.zeros(1, 4, 8)) + assert "IGNORED" not in status + assert capsys.readouterr().out == "" + + +def test_clip_alone_says_nothing_extra(monkeypatch, capsys): + node = FunPackVideoRefinerV2() + _cond, _meta, status, owner = _source(node, _StubClip(), None, monkeypatch) + assert owner == "CLIP-owned" + assert "IGNORED" not in status + assert capsys.readouterr().out == ""