Skip to content

[Issue 101][eval-and-fix] Fix VideoAutoencoderKL.forward return contract (closes pollockjj/mydevelopment#190)#44

Merged
pollockjj merged 2 commits into
issue_101from
issue_190
May 5, 2026
Merged

[Issue 101][eval-and-fix] Fix VideoAutoencoderKL.forward return contract (closes pollockjj/mydevelopment#190)#44
pollockjj merged 2 commits into
issue_101from
issue_190

Conversation

@pollockjj
Copy link
Copy Markdown
Owner

Plan: Fix VideoAutoencoderKL.forward to honor tensor/tuple return contract

Overview

VideoAutoencoderKL.forward() on pollockjj/ComfyUI:issue_101 dereferences
diffusers-style .latent_dist and .sample attributes on values that are
already plain torch.Tensor (or one-element tuple) returns from encode()
and decode_(). Direct module invocation via forward(x, mode=…) raises
AttributeError immediately, and the mode == "decode" branch additionally
calls self.decode(x) on a class that does not define decode (only
decode_). The fix replaces the buggy attribute access with the actual
return contract and adds a regression test that exercises forward() for
mode="encode", mode="decode", and mode="all" and asserts each return is
a torch.Tensor of the expected shape — binary equality, no tolerance bands.

Diagnosis Summary

The buggy method body, captured live from issue_101:comfy/ldm/seedvr/vae.py
lines 2194–2207 (Ground Truth Probe GTP-3):

def forward(
    self, x: torch.FloatTensor, mode: Literal["encode", "decode", "all"] = "all", **kwargs
):
    # x: [b c t h w]
    if mode == "encode":
        h = self.encode(x)
        return h.latent_dist
    elif mode == "decode":
        h = self.decode(x)
        return h.sample
    else:
        h = self.encode(x)
        h = self.decode(h.latent_dist.mode())
        return h.sample

Live AST probe of VideoAutoencoderKL (GTP-1) confirms the class defines
encode, decode_, and forward, but has no decode member. The actual
encode() body (GTP-2) returns the tensor posterior = DiagonalGaussianDistribution(h).mode() when return_dict=True (the default
under forward's call site) and (posterior,) when return_dict=False.
decode_() mirrors that contract — decoded (tensor) by default, (decoded,)
when return_dict=False. None of those returns expose .latent_dist or
.sample. Every code path of the current forward raises before producing a
result. Fix shape: route through self.decode_ (with the trailing
underscore), return tensors directly, and tolerate the optional one-element
tuple shape that return_dict=False would produce.

Reproduction command: `cd /home/johnj/dev_cuda_1/ComfyUI && python3 -m pytest tests-unit/comfy_test/seedvr_vae_forward_test.py -v`
Observed failure: pre-fix run raises `AttributeError` in the encode/decode/all paths as described below.

The pre-fix runs against issue_101:comfy/ldm/seedvr/vae.py raise
AttributeError: 'Tensor' object has no attribute 'latent_dist' for
mode="encode" and mode="all", and AttributeError: 'VideoAutoencoderKL' object has no attribute 'decode' for mode="decode". The same invocation
post-fix exits 0 with 4 passed. AC-1 / AC-2 capture this A/B pair as
committed pytest logs.

Affected Repositories

Repository Path Base Branch Issue Branch
pollockjj/ComfyUI /home/johnj/dev_cuda_1/ComfyUI issue_101 issue_190
pollockjj/mydevelopment /home/johnj/dev_cuda_1/mydevelopment main issue_190

pollockjj/ComfyUI is the deliverable: the fix to comfy/ldm/seedvr/vae.py
and the new regression test under tests-unit/comfy_test/ land here on
issue_190 and PR back into issue_101.

pollockjj/mydevelopment is the bookkeeping target: every committed
artifact under github_issues/190/slice1/ (pytest logs, source extracts,
diff transcripts, grep transcripts) lives on the outer workspace's
issue_190 branch and PRs back into main as the standard
[bookkeeping] [Issue 101][eval-and-fix] pattern (see merged PRs Comfy-Org#197Comfy-Org#201
for the precedent).

Asset Readiness

Asset Location Provenance Status Evidence
ComfyUI deliverable checkout /home/johnj/dev_cuda_1/ComfyUI pollockjj/ComfyUI branch issue_101 -> issue_190 VERIFIED branch/path verified before slice execution
Python test environment /home/johnj/dev_cuda_1/ComfyUI/.venv/ local-only with no upstream VERIFIED pytest/torch invocation succeeds on slot
Base-branch source under test issue_101:comfy/ldm/seedvr/vae.py pollockjj/ComfyUI issue_101 VERIFIED GTP-1, GTP-2, GTP-3
Bookkeeping workspace /home/johnj/dev_cuda_1/mydevelopment pollockjj/mydevelopment main -> issue_190 VERIFIED artifact paths under github_issues/190/slice1/ are writable/tracked

Research and Methodology

Plan Foundations Comment URL: https://github.com/pollockjj/mydevelopment/issues/190#issuecomment-4378366792

Plan Foundations Comment Pin: comment-id=IC_kwDOR2e1q88AAAABBPiTSA edited-at=2026-05-05T10:19:01Z

Detected Scope: none — trivial bug-fix where the existing encode() /
decode_() return contract IS the spec; the fix duplicates that contract
correctly inside forward() and adds a regression test that locks the
contract.

The change class is "honor an existing internal API contract." No external
research, no canonical references, no metric definitions, and no published
anchor are invoked. The equivalence rule is binary type/shape equality
on the tensors returned by forward()type(result) is torch.Tensor and
result.shape == expected_shape. No tolerance bands; no statistical tests.
Source authority is the live source of comfy/ldm/seedvr/vae.py on the
issue's base branch (issue_101), captured verbatim under
## Ground Truth Probes.

Binding parent-issue directives quoted verbatim from
pollockjj/mydevelopment#190 issue body (the tracking issue this plan
finalizes):

"The fix must route through decode_ on this class; do NOT invent a new
decode method on the parent class."

"Adjacent VideoAutoencoderKLWrapper.forward has the same bug class but
is tracked separately as Comfy-Org#192; do NOT modify that method here."

"Any change to encode() / decode_() signatures or return shapes is
out of scope and indicates plan drift — stop and surface."

These three directives bound the scope of every AC below.

Tools, Pipeline, and Measurements

Plan Foundations Comment URL: https://github.com/pollockjj/mydevelopment/issues/190#issuecomment-4378366792

Plan Foundations Comment Pin: comment-id=IC_kwDOR2e1q88AAAABBPiTSA edited-at=2026-05-05T10:19:01Z

Existing tooling — REUSE only. Trivial scope; no external tools beyond
the change itself.

Tool / Dep / Repo Version / SHA Status Citation
pytest repo tests-unit/requirements.txt pin (per tests-unit/README.md) REUSE git show issue_101:tests-unit/README.md documents pytest tests-unit/ as the canonical invocation
torch repo .venv/ pin on the deliverable slot /home/johnj/dev_cuda_1/ComfyUI/.venv/ REUSE already on the slot per CLAUDE.md slot layout
comfy.ldm.seedvr.vae.VideoAutoencoderKL issue_101 HEAD REUSE live AST + import probe captured as GTP-1
git system REUSE for diff/log artifacts

Pipeline: edit one method body in one source file → add one test file →
run pytest against the new test on issue_190 (post-fix) and against
the same test with vae.py reverted to issue_101:comfy/ldm/seedvr/vae.py
(pre-fix) → commit pytest logs, AST-extracted forward source, grep
transcripts, and a scope-bounded git diff to github_issues/190/slice1/
on the bookkeeping branch.

Measurements: the only "measurement" is binary type and shape equality on
three tensor returns from forward(). There is no metric, no anchor, no
statistical test, no sweep, and no characterization verdict. Single-probe
and boundary-bracketing requirements (HR-06, HR-11) do not apply.

Ground Truth Probes

Probe ID Consumed by AC(s) Probe command Observed output (verbatim)
GTP-1 Slice 1 AC-3, AC-5, AC-6, AC-7 cd /home/johnj/dev_cuda_1/ComfyUI && git show issue_101:comfy/ldm/seedvr/vae.py | python3 -c 'import ast,sys; tree=ast.parse(sys.stdin.read()); [print("class VideoAutoencoderKL methods:", [m.name for m in n.body if isinstance(m,(ast.FunctionDef,ast.AsyncFunctionDef))]) for n in ast.walk(tree) if isinstance(n,ast.ClassDef) and n.name=="VideoAutoencoderKL"]' class VideoAutoencoderKL methods: ['__init__', 'encode', 'decode_', '_encode', '_decode', 'slicing_encode', 'slicing_decode', 'tiled_encode', 'tiled_decode', 'forward'] — i.e. encode, decode_, and forward are members; decode (no underscore) is NOT a member
GTP-2 Slice 1 AC-1, AC-2, AC-7 cd /home/johnj/dev_cuda_1/ComfyUI && git show issue_101:comfy/ldm/seedvr/vae.py | sed -n '2101,2118p'
    def encode(self, x: torch.FloatTensor, return_dict: bool = True):
h = self.slicing_encode(x)
posterior = DiagonalGaussianDistribution(h).mode()

if not return_dict:
return (posterior,)

return posterior

def decode_(
self, z: torch.Tensor, return_dict: bool = True
):
decoded = self.slicing_decode(z)

if not return_dict:
return (decoded,)

return decoded
i.e. encode/decode_ return a tensor when return_dict=True (the default at the forward call site) and a one-element tuple (tensor,) when return_dict=False. Neither return path produces an object with .latent_dist or .sample.
GTP-3 Slice 1 AC-1, AC-3, AC-4, AC-5 cd /home/johnj/dev_cuda_1/ComfyUI && git show issue_101:comfy/ldm/seedvr/vae.py | sed -n '2194,2208p'
    def forward(
self, x: torch.FloatTensor, mode: Literal["encode", "decode", "all"] = "all", **kwargs
):
# x: [b c t h w]
if mode == "encode":
h = self.encode(x)
return h.latent_dist
elif mode == "decode":
h = self.decode(x)
return h.sample
else:
h = self.encode(x)
h = self.decode(h.latent_dist.mode())
return h.sample
i.e. the buggy method (a) accesses .latent_dist on lines 2200/2206, (b) accesses .sample on lines 2203/2207, and (c) calls self.decode(...) on lines 2202/2206 — three distinct AttributeError sites that the fix removes.
GTP-4 Slice 1 AC-6 cd /home/johnj/dev_cuda_1/ComfyUI && git show issue_101:comfy/ldm/seedvr/vae.py | python3 -c 'import ast,sys; tree=ast.parse(sys.stdin.read()); [print("class VideoAutoencoderKLWrapper methods:", [m.name for m in n.body if isinstance(m,(ast.FunctionDef,ast.AsyncFunctionDef))]) for n in ast.walk(tree) if isinstance(n,ast.ClassDef) and n.name=="VideoAutoencoderKLWrapper"]' class VideoAutoencoderKLWrapper methods: ['__init__', 'forward', 'encode', 'decode', 'set_memory_limit'] — combined with the AST-extracted body of VideoAutoencoderKLWrapper.forward from the same source, captured via python3 -c 'import ast,sys; src=sys.stdin.read(); tree=ast.parse(src); [print(ast.get_source_segment(src,m)) for n in ast.walk(tree) if isinstance(n,ast.ClassDef) and n.name=="VideoAutoencoderKLWrapper" for m in n.body if isinstance(m,ast.FunctionDef) and m.name=="forward"]', yielding
def forward(self, x: torch.FloatTensor):
with torch.no_grad() if self.freeze_encoder else nullcontext():
z, p = self.encode(x)
x = self.decode(z).sample
return x, z, p
. Both literal output blocks were captured live on issue_101 HEAD; AC-6 cites GTP-4 to lock the wrapper class methods and forward body as the off-limits surface that the scope-diff artifact must not touch.
GTP-5 Slice 1 AC-7 cd /home/johnj/dev_cuda_1/ComfyUI && git ls-tree --name-only issue_101 tests-unit/comfy_test/
tests-unit/comfy_test/folder_path_test.py
tests-unit/comfy_test/model_detection_test.py
i.e. on issue_101, tests-unit/comfy_test/ contains exactly two files (folder_path_test.py and model_detection_test.py) and zero seedvr coverage. AC-7's pre-fix-fingerprint cites GTP-5 to lock the absence of any seedvr_vae_forward_test.py on the base branch.

Every literal API surface the ACs below cite — VideoAutoencoderKL,
encode, decode_, forward, the mode parameter and its Literal
values "encode" / "decode" / "all", the .latent_dist and .sample
attribute references in the buggy body, the self.decode( call site
that must become self.decode_(, the off-limits VideoAutoencoderKLWrapper
class and its forward body, and the base-branch tests-unit/comfy_test/
directory contents — is anchored to one of GTP-1, GTP-2, GTP-3, GTP-4,
GTP-5 above.

Created Surface Contract

Surface Created by Contract
tests-unit/comfy_test/seedvr_vae_forward_test.py Slice 1 New file in pollockjj/ComfyUI on issue_190. Defines four pytest test functions that exercise VideoAutoencoderKL.forward() against a stub subclass (which bypasses the heavy __init__ via torch.nn.Module.__init__(self) and overrides encode/decode_ with known tensors): test_forward_encode_returns_tensor, test_forward_decode_returns_tensor, test_forward_all_returns_tensor, test_forward_source_has_no_diffusers_attr_access. The first three assert type(result) is torch.Tensor and result.shape == expected_shape for each mode. The fourth uses inspect.getsource(VideoAutoencoderKL.forward) and asserts ".latent_dist" not in src, ".sample" not in src, and a regex r"self\.decode\(" (open paren, no underscore) does not match.
github_issues/190/slice1/pytest_post_fix.log Slice 1 Committed to pollockjj/mydevelopment issue_190. Verbatim stdout/stderr of cd /home/johnj/dev_cuda_1/ComfyUI && python3 -m pytest tests-unit/comfy_test/seedvr_vae_forward_test.py -v run on issue_190 HEAD. Final line contains 4 passed.
github_issues/190/slice1/pytest_pre_fix.log Slice 1 Committed to pollockjj/mydevelopment issue_190. Verbatim stdout/stderr of the same pytest invocation captured after git checkout issue_101 -- comfy/ldm/seedvr/vae.py is applied to the deliverable working tree. Captures three AttributeError failures on the encode/decode/all tests plus the source-shape assertion failure. Restored to issue_190 HEAD via git restore comfy/ldm/seedvr/vae.py immediately after capture.
github_issues/190/slice1/forward_source.txt Slice 1 Committed to pollockjj/mydevelopment issue_190. Verbatim AST-extracted source of VideoAutoencoderKL.forward from issue_190 HEAD comfy/ldm/seedvr/vae.py, produced by python3 -c 'import ast; src=open("comfy/ldm/seedvr/vae.py").read(); tree=ast.parse(src); cls=[n for n in ast.walk(tree) if isinstance(n,ast.ClassDef) and n.name=="VideoAutoencoderKL"][0]; m=[n for n in cls.body if isinstance(n,ast.FunctionDef) and n.name=="forward"][0]; print(ast.get_source_segment(src,m))'.
github_issues/190/slice1/forbidden_attrs_grep.log Slice 1 Committed to pollockjj/mydevelopment issue_190. Output of grep -n -E '\.latent_dist|\.sample' github_issues/190/slice1/forward_source.txt. Exit code 1, zero lines.
github_issues/190/slice1/decode_call_grep.log Slice 1 Committed to pollockjj/mydevelopment issue_190. Output of grep -n -E 'self\.decode\(' github_issues/190/slice1/forward_source.txt. Exit code 1, zero lines. (self.decode_( is permitted; the regex requires an open paren immediately after decode.)
github_issues/190/slice1/scope_diff.txt Slice 1 Committed to pollockjj/mydevelopment issue_190. Output of cd /home/johnj/dev_cuda_1/ComfyUI && git diff issue_101..issue_190 -- comfy/ldm/seedvr/vae.py. The diff shows zero hunks outside the body of VideoAutoencoderKL.forward (lines 2194–2207 on the issue_101 side); encode, decode_, _encode, _decode, slicing_encode, slicing_decode, tiled_encode, tiled_decode, and VideoAutoencoderKLWrapper are all unchanged.

Slices


Slice 1: Fix VideoAutoencoderKL.forward tensor/tuple contract

Kind: implementation

Objective: Prove that VideoAutoencoderKL.forward() returns plain torch.Tensor values for mode="encode", mode="decode", and mode="all" without dereferencing .latent_dist or .sample, and that the change is scoped strictly to the body of VideoAutoencoderKL.forward (no other method body or class touched).

Acceptance Criteria

  • AC-1: cd /home/johnj/dev_cuda_1/ComfyUI && python3 -m pytest tests-unit/comfy_test/seedvr_vae_forward_test.py -v exits 0 with 4 passed in the summary line — verified by committed artifact github_issues/190/slice1/pytest_post_fix.log whose last non-blank line ends with 4 passed.
    • Pre-fix-fingerprint: same pytest invocation against the issue_101 source raises AttributeError: 'Tensor' object has no attribute 'latent_dist' (and analogous .sample / decode errors) on every encode/decode/all test (Diagnosis Summary §"Diagnosis Summary"; GTP-3)
    • Post-fix-expectation: zero exceptions; pytest exits 0; summary line contains 4 passed
    • Assumes-passed: none
    • In-scope-of: Slice 1 Objective "Prove that VideoAutoencoderKL.forward() returns plain torch.Tensor values for mode="encode", mode="decode", and mode="all" without dereferencing .latent_dist or .sample, and that the change is scoped strictly to the body of VideoAutoencoderKL.forward (no other method body or class touched)."
    • Probe: GTP-2, GTP-3
    • Foundations-pin: comment-id=IC_kwDOR2e1q88AAAABBPiTSA edited-at=2026-05-05T10:19:01Z
  • AC-2: The committed A/B pytest pair for tests-unit/comfy_test/seedvr_vae_forward_test.py -v proves the same observable flips across the fix: github_issues/190/slice1/pytest_pre_fix.log records at least three AttributeError failures plus the test_forward_source_has_no_diffusers_attr_access failure after cd /home/johnj/dev_cuda_1/ComfyUI && git checkout issue_101 -- comfy/ldm/seedvr/vae.py, and github_issues/190/slice1/pytest_post_fix.log records pytest exit 0 with 4 passed after git restore comfy/ldm/seedvr/vae.py restores issue_190 HEAD.
    • Pre-fix-fingerprint: the same python3 -m pytest tests-unit/comfy_test/seedvr_vae_forward_test.py -v invocation raises AttributeError in the encode/decode/all paths when vae.py is reverted to issue_101 (Diagnosis Summary §"Diagnosis Summary"; GTP-3)
    • Post-fix-expectation: the same pytest invocation on restored issue_190 HEAD exits 0 with 4 passed and zero AttributeError failures
    • Assumes-passed: none
    • In-scope-of: Slice 1 Objective "Prove that VideoAutoencoderKL.forward() returns plain torch.Tensor values for mode="encode", mode="decode", and mode="all" without dereferencing .latent_dist or .sample, and that the change is scoped strictly to the body of VideoAutoencoderKL.forward (no other method body or class touched)."
    • Probe: GTP-2, GTP-3
    • Foundations-pin: comment-id=IC_kwDOR2e1q88AAAABBPiTSA edited-at=2026-05-05T10:19:01Z
  • AC-3: The AST-extracted body of VideoAutoencoderKL.forward on issue_190 HEAD contains zero occurrences of the literal .latent_dist — verified by committed artifacts github_issues/190/slice1/forward_source.txt (the extracted body) and github_issues/190/slice1/forbidden_attrs_grep.log (grep -n -E '\.latent_dist|\.sample' forward_source.txt exit code 1, zero matching lines).
    • Pre-fix-fingerprint: GTP-3 captures two .latent_dist occurrences on lines 2200 and 2206 of issue_101's vae.py
    • Post-fix-expectation: zero .latent_dist references survive in the post-fix forward body; the grep log is empty
    • Assumes-passed: none
    • In-scope-of: Slice 1 Objective "Prove that VideoAutoencoderKL.forward() returns plain torch.Tensor values for mode="encode", mode="decode", and mode="all" without dereferencing .latent_dist or .sample, and that the change is scoped strictly to the body of VideoAutoencoderKL.forward (no other method body or class touched)."
    • Probe: GTP-3
    • Foundations-pin: comment-id=IC_kwDOR2e1q88AAAABBPiTSA edited-at=2026-05-05T10:19:01Z
  • AC-4: The AST-extracted body of VideoAutoencoderKL.forward on issue_190 HEAD contains zero occurrences of the literal .sample — verified by the same committed artifacts as AC-3 (forward_source.txt plus forbidden_attrs_grep.log); the same combined grep covers both literals and reports zero matches for either.
    • Pre-fix-fingerprint: GTP-3 captures two .sample occurrences on lines 2203 and 2207 of issue_101's vae.py
    • Post-fix-expectation: zero .sample references survive in the post-fix forward body
    • Assumes-passed: none
    • In-scope-of: Slice 1 Objective "Prove that VideoAutoencoderKL.forward() returns plain torch.Tensor values for mode="encode", mode="decode", and mode="all" without dereferencing .latent_dist or .sample, and that the change is scoped strictly to the body of VideoAutoencoderKL.forward (no other method body or class touched)."
    • Probe: GTP-3
    • Foundations-pin: comment-id=IC_kwDOR2e1q88AAAABBPiTSA edited-at=2026-05-05T10:19:01Z
  • AC-5: The AST-extracted body of VideoAutoencoderKL.forward on issue_190 HEAD contains zero occurrences of the regex self\.decode\( (open paren immediately after decode, no trailing underscore) — verified by committed artifact github_issues/190/slice1/decode_call_grep.log (grep -n -E 'self\.decode\(' forward_source.txt exit code 1, zero matching lines). self.decode_( references — if the implementer chooses to call self.decode_ for mode="decode" and mode="all" — are permitted because the regex requires the next character after decode to be (.
    • Pre-fix-fingerprint: GTP-3 captures two self.decode( call sites on lines 2202 and 2206 of issue_101's vae.py; GTP-1 confirms decode is not defined on the class
    • Post-fix-expectation: zero self.decode( (open-paren-immediately) call sites remain; route is exclusively through self.decode_
    • Assumes-passed: none
    • In-scope-of: Slice 1 Objective "Prove that VideoAutoencoderKL.forward() returns plain torch.Tensor values for mode="encode", mode="decode", and mode="all" without dereferencing .latent_dist or .sample, and that the change is scoped strictly to the body of VideoAutoencoderKL.forward (no other method body or class touched)."
    • Probe: GTP-1, GTP-3
    • Foundations-pin: comment-id=IC_kwDOR2e1q88AAAABBPiTSA edited-at=2026-05-05T10:19:01Z
  • AC-6: cd /home/johnj/dev_cuda_1/ComfyUI && git diff issue_101..issue_190 -- comfy/ldm/seedvr/vae.py produces hunks confined to the line range of VideoAutoencoderKL.forward on the issue_101 side (lines 2194–2207 per GTP-3) and zero hunks touching encode, decode_, _encode, _decode, slicing_encode, slicing_decode, tiled_encode, tiled_decode, or any line of VideoAutoencoderKLWrapper (per GTP-4) — verified by committed artifact github_issues/190/slice1/scope_diff.txt. The artifact contains the verbatim diff plus a final stanza listing every @@-hunk header range and confirming each falls inside [2194, 2207] on the - side.
    • Pre-fix-fingerprint: the only intentional change in this slice is the body of one method; any hunk outside that body would prove unintended drift to call sites that the issue body lists as out of scope (VideoAutoencoderKLWrapper.forward per Add support for file list refresh feature in node Comfy-Org/ComfyUI#192 — captured live as GTP-4, encode/decode_ signatures per "plan drift" guard)
    • Post-fix-expectation: every diff hunk on the vae.py side is confined to the forward method body; the artifact's final stanza enumerates each hunk and asserts in-range
    • Assumes-passed: none
    • In-scope-of: Slice 1 Objective "Prove that VideoAutoencoderKL.forward() returns plain torch.Tensor values for mode="encode", mode="decode", and mode="all" without dereferencing .latent_dist or .sample, and that the change is scoped strictly to the body of VideoAutoencoderKL.forward (no other method body or class touched)."
    • Probe: GTP-1, GTP-3, GTP-4
    • Foundations-pin: comment-id=IC_kwDOR2e1q88AAAABBPiTSA edited-at=2026-05-05T10:19:01Z
  • AC-7: The committed test file tests-unit/comfy_test/seedvr_vae_forward_test.py on issue_190 defines four pytest test functions whose names are exactly test_forward_encode_returns_tensor, test_forward_decode_returns_tensor, test_forward_all_returns_tensor, and test_forward_source_has_no_diffusers_attr_access; the first three assert both type(result) is torch.Tensor and an exact result.shape == expected_shape equality (binary, no tolerance band) for each mode; the fourth runs inspect.getsource(VideoAutoencoderKL.forward) and asserts the absence of .latent_dist, .sample, and the regex r"self\.decode\(" — verified by committed artifact github_issues/190/slice1/test_source.txt (cp /home/johnj/dev_cuda_1/ComfyUI/tests-unit/comfy_test/seedvr_vae_forward_test.py github_issues/190/slice1/test_source.txt) plus the AC-1 pytest log showing all four test names in the PASSED lines.
    • Pre-fix-fingerprint: prior to this slice, tests-unit/comfy_test/ on issue_101 contains exactly two files (folder_path_test.py and model_detection_test.py) per GTP-5, so the regression test does not yet exist on the base branch
    • Post-fix-expectation: the test file exists with all four named functions; AC-1's pytest log lists PASSED for each by name; the binary type/shape assertions exclude tolerance-band variants
    • Assumes-passed: none
    • In-scope-of: Slice 1 Objective "Prove that VideoAutoencoderKL.forward() returns plain torch.Tensor values for mode="encode", mode="decode", and mode="all" without dereferencing .latent_dist or .sample, and that the change is scoped strictly to the body of VideoAutoencoderKL.forward (no other method body or class touched)."
    • Probe: GTP-1, GTP-2, GTP-5
    • Foundations-pin: comment-id=IC_kwDOR2e1q88AAAABBPiTSA edited-at=2026-05-05T10:19:01Z

Constraints

  • Python: python3
  • Runner: python3 -m pytest tests-unit/comfy_test/seedvr_vae_forward_test.py -v from the deliverable checkout root /home/johnj/dev_cuda_1/ComfyUI
  • No packages installed into host venv; the deliverable slot's .venv/ already provides torch and pytest per the slot layout in CLAUDE.md
  • No pkill, no rm -rf, no python main.py, no /tmp writes
  • One command per shell call; no &&/||/; chaining
  • All deliverable code commits land on pollockjj/ComfyUI:issue_190 cut from issue_101; PR target = issue_101
  • All bookkeeping evidence commits (github_issues/190/slice1/*) land on pollockjj/mydevelopment:issue_190 cut from main; PR target = main
  • Zero modifications to any method other than VideoAutoencoderKL.forward in comfy/ldm/seedvr/vae.py (encode, decode_, _encode, _decode, slicing_encode, slicing_decode, tiled_encode, tiled_decode, and the entire VideoAutoencoderKLWrapper class are off-limits)
  • Zero changes to encode() / decode_() signatures or return shapes (issue body explicit "plan drift" guard)
  • Relevant Existing Tooling:
    • pytest from the deliverable slot's .venv/ — REUSE; no install
    • comfy.ldm.seedvr.vae.VideoAutoencoderKL import path — REUSE; verified by GTP-1
    • git, grep, AST extraction via stdlib ast module — REUSE
    • The new test file is the only added Python source in the deliverable; the new artifacts under github_issues/190/slice1/ are the only added paths in the bookkeeping repo
  • Evidence Primitive Requirements:
    • Behavior change (forward stops raising AttributeError) → A/B pytest pair: post-fix log on issue_190 HEAD plus pre-fix log captured with vae.py transiently reverted to issue_101 (AC-1, AC-2)
    • Source shape claim (no .latent_dist, .sample, self.decode( in forward body) → AST-extracted committed source plus zero-match grep transcripts (AC-3, AC-4, AC-5)
    • Scope claim (only forward changed) → committed git diff issue_101..issue_190 -- vae.py with hunk-range enumeration (AC-6)
    • Test surface claim (four named functions with binary assertions) → committed copy of the test source plus pytest log naming each function as PASSED (AC-7)
  • Repository Hygiene:
    • Every dirty repo state on either deliverable or bookkeeping checkout is resolved by the agent without git stash or external decision deferral.
    • Dirty paths are classified as committed work, precise committed .gitignore rules for safe generated bulk, or discarded generated debris.
    • Clean committed work already present on issue_190 (e.g. the ?? github_issues/190/ dispatch artifacts seen at plan time on the bookkeeping checkout) is repo provenance and is integrated, not removed as dirty-state cleanup.
    • Slicers and Melian must run live git status --short gates locally on both /home/johnj/dev_cuda_1/ComfyUI and /home/johnj/dev_cuda_1/mydevelopment and must refuse to submit while either is dirty.
    • Plans must not require repo_hygiene.txt, raw git status --short transcripts, or CLEAN markers as QA evidence.
    • QA verifies submitted commits, branch refs, and artifact presence through GitHub rather than trusting slicer-authored cleanliness transcripts.
    • The transient revert in AC-2 (git checkout issue_101 -- comfy/ldm/seedvr/vae.py) MUST be undone via git restore comfy/ldm/seedvr/vae.py before any commit is created on the deliverable; the pre-fix log itself is committed only to the bookkeeping repo.

Out of Scope

  • VideoAutoencoderKLWrapper.forward (lines 2226–2230 on issue_101) — same bug class (self.decode(z).sample) but tracked separately as pollockjj/mydevelopment#192. Do not touch.
  • Any change to VideoAutoencoderKL.encode() or VideoAutoencoderKL.decode_() — signature, return shape, or body. The issue body explicitly flags such changes as plan drift; if implementation reveals a need to change them, stop and surface to the architect.
  • Any change to comfy_extras/nodes_seedvr.py, tiled_vae, or other call sites of encode() / decode_() outside VideoAutoencoderKL.forward. The fix is scoped to one method body.
  • Upstream propagation of the fix to feat: Add support For SeedVR2 (CORE-6) Comfy-Org/ComfyUI#11294. The upstream PR is mergeable=DIRTY and silent for two weeks per the issue body; pushing back to yousef-rafat:seedvr2 is out of scope and requires a separate decision.
  • Numeric correctness of the encode→decode round trip on real weights. The regression test exercises the return-type/return-shape contract with stub returns; correctness of the mathematical pipeline is covered by the existing seedvr workflow integration on issue_101 and is not re-validated by this slice.
  • Tolerance-band assertions of any kind. The fix is a contract repair; equality is binary (type(result) is torch.Tensor, result.shape == expected_shape).
  • Removal or refactor of the **kwargs parameter on forward. Honoring the call-site contract is sufficient; the parameter list stays as captured in GTP-3.

Tracked in pollockjj/mydevelopment Comfy-Org#190 (bookkeeping PR pollockjj/mydevelopment#203).

…AutoencoderKL.forward (closes pollockjj/mydevelopment#190)

VideoAutoencoderKL.forward dereferenced .latent_dist and .sample on
encode()/decode_() returns and called self.decode (no underscore) on a
class that only defines decode_. Direct module invocation via
forward(x, mode=...) raised AttributeError on every path.

encode() / decode_() return a tensor when return_dict=True (the call
site default) and a one-element tuple when return_dict=False. The fix
unwraps that optional tuple shape and routes mode="decode" / mode="all"
through self.decode_ (with the trailing underscore) so the actual
contract is honored without changing either method signature.

Regression test tests-unit/comfy_test/seedvr_vae_forward_test.py
exercises forward() for mode="encode", "decode", and "all" against a
stub subclass that bypasses the heavy __init__, plus an
inspect.getsource assertion that no .latent_dist, no .sample, and no
self.decode( call survive in the post-fix forward body.

Source: CodeRabbit thread on Comfy-Org#11294
Comfy-Org#11294 (comment)
Copilot AI review requested due to automatic review settings May 5, 2026 15:40
@qa-agent-seveneves
Copy link
Copy Markdown

Codex Review -- Round 1 -- KICKOFF

Runner: scripts/run_codex_review.py
PR: #44
Reviewer model: codex review (configured codex CLI default)
Kickoff timestamp (UTC): 2026-05-05T15:42:12Z

Prompt sent to codex review

Review the latest state of https://github.com/pollockjj/ComfyUI/pull/44. Output findings using strict P0-P3 priority tags ([P0], [P1], [P2], [P3]) at the start of each finding title. Surface P0/P1/P2 -- these block merge in this repo. Surface P3 with that tag explicitly. Do not surface style nits, formatting, typos, or pre-existing bugs. End your output with a single line -- one of: 'APPROVE' (no P0/P1/P2 found), 'REVIEW CONDUCTED AND NO ISSUES FOUND' (no P0/P1/P2 found, equivalent to APPROVE for verdict-tracking purposes; use this if you are reluctant to emit a bare APPROVE token), or 'REQUEST_CHANGES' (one or more P0/P1/P2 found). Output nothing else after that line.

Awaiting codex output. The result will be posted as a separate comment on this PR when codex exits.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes VideoAutoencoderKL.forward() in SeedVR so it uses this class’s actual encode() / decode_() return shapes instead of diffusers-style attributes. This is a narrow contract-repair in the VAE plus a new regression test file to pin the behavior.

Changes:

  • Replaced invalid .latent_dist / .sample access in VideoAutoencoderKL.forward() with direct tensor handling.
  • Switched the decode path from nonexistent self.decode(...) to self.decode_(...).
  • Added SeedVR unit tests covering forward(..., mode="encode"|"decode"|"all") plus a source-level guard against reintroducing the old pattern.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
comfy/ldm/seedvr/vae.py Repairs VideoAutoencoderKL.forward() to call encode() / decode_() directly and unwrap tuple returns.
tests-unit/comfy_test/seedvr_vae_forward_test.py Adds regression tests for forward return types/shapes and a source-level pin for the removed diffusers-style access.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread comfy/ldm/seedvr/vae.py
Comment on lines 2201 to +2207
if mode == "encode":
h = self.encode(x)
return h.latent_dist
return _unwrap(self.encode(x))
elif mode == "decode":
h = self.decode(x)
return h.sample
return _unwrap(self.decode_(x))
else:
h = self.encode(x)
h = self.decode(h.latent_dist.mode())
return h.sample
latent = _unwrap(self.encode(x))
return _unwrap(self.decode_(latent))
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The kwargs-propagation observation is correct in isolation: forward(x, return_dict=False) does not propagate to encode()/decode_(). However, this PR's stated scope is the AttributeError from .latent_dist/.sample access on tensor returns; the _unwrap handles both single-tensor returns AND the (z, p) 2-tuple from VideoAutoencoderKLWrapper.encode. Honoring return_dict=False end-to-end is a separate concern and would belong in a follow-up issue.

Comment on lines +50 to +54
def encode(self, x, return_dict=True):
return self._encode_out

def decode_(self, z, return_dict=True):
return self._decode_out
Comment on lines +81 to +85
def test_forward_source_has_no_diffusers_attr_access():
src = inspect.getsource(VideoAutoencoderKL.forward)
assert ".latent_dist" not in src
assert ".sample" not in src
assert re.search(r"self\.decode\(", src) is None
@qa-agent-seveneves
Copy link
Copy Markdown

Codex Review -- Round 1 -- RESULT

PR: #44
Reviewer model: codex review (configured codex CLI default)
Result timestamp (UTC): 2026-05-05T15:44:14Z
Codex exit code: 0
Duration (s): 120.2
Detected verdict: UNKNOWN

Prompt sent to codex review

Review the latest state of https://github.com/pollockjj/ComfyUI/pull/44. Output findings using strict P0-P3 priority tags ([P0], [P1], [P2], [P3]) at the start of each finding title. Surface P0/P1/P2 -- these block merge in this repo. Surface P3 with that tag explicitly. Do not surface style nits, formatting, typos, or pre-existing bugs. End your output with a single line -- one of: 'APPROVE' (no P0/P1/P2 found), 'REVIEW CONDUCTED AND NO ISSUES FOUND' (no P0/P1/P2 found, equivalent to APPROVE for verdict-tracking purposes; use this if you are reluctant to emit a bare APPROVE token), or 'REQUEST_CHANGES' (one or more P0/P1/P2 found). Output nothing else after that line.

Verbatim codex review output

This PR was reviewed using codex review with the prompt above and produced the following output:


No merge-blocking correctness issues were identified in the PR diff.


Codex runner stderr (non-evidence)

OpenAI Codex v0.128.0 (research preview)
--------
workdir: /home/johnj/dev_master/mydevelopment
model: gpt-5.5
provider: openai
approval: never
sandbox: workspace-write [workdir, /tmp, /home/johnj/.codex/memories]
reasoning effort: high
reasoning summaries: none
session id: 019df8cd-dd3b-7111-9f67-66dd23553283
--------
user
Review the latest state of https://github.com/pollockjj/ComfyUI/pull/44. Output findings using strict P0-P3 priority tags ([P0], [P1], [P2], [P3]) at the start of each finding title. Surface P0/P1/P2 -- these block merge in this repo. Surface P3 with that tag explicitly. Do not surface style nits, formatting, typos, or pre-existing bugs. End your output with a single line -- one of: 'APPROVE' (no P0/P1/P2 found), 'REVIEW CONDUCTED AND NO ISSUES FOUND' (no P0/P1/P2 found, equivalent to APPROVE for verdict-tracking purposes; use this if you are reluctant to emit a bare APPROVE token), or 'REQUEST_CHANGES' (one or more P0/P1/P2 found). Output nothing else after that line.
exec
/bin/bash -lc pwd in /home/johnj/dev_master/mydevelopment
 succeeded in 0ms:
/home/johnj/dev_master/mydevelopment

exec
/bin/bash -lc 'ls .agent/rules' in /home/johnj/dev_master/mydevelopment
 succeeded in 0ms:
anti-patterns.md
architect-context.md
attribution.md
autonomous-skill-execution.md
development-infrastructure.md
golden-rules.md
guard-rails.md
mandatory-reads.md
mission.md
operating-modes.md
standing-parameters.md

exec
/bin/bash -lc 'cat .agent/rules/anti-patterns.md .agent/rules/architect-context.md .agent/rules/attribution.md .agent/rules/autonomous-skill-execution.md .agent/rules/development-infrastructure.md .agent/rules/golden-rules.md .agent/rules/guard-rails.md .agent/rules/mandatory-reads.md .agent/rules/mission.md .agent/rules/operating-modes.md .agent/rules/standing-parameters.md' in /home/johnj/dev_master/mydevelopment
 succeeded in 0ms:
<!-- Auto-generated from CLAUDE.md. Do not edit directly. -->
<!-- Regenerate: python scripts/generate_agent_configs.py -->

## Anti-Patterns (FORBIDDEN)

1. **Interpreting** - User's direct, specific queries are instructions. QUESTIONS ARE TO BE ANSWERED, THEN AWAIT INSTRUCTION, NOT IMPLEMENT.
2. **Bypassing** - Skipping, quiet-failing tests or otherwise justifying not faithfully executing instructions to proceed rather than failing loudly.
3. **Assuming** - Code other than your own modifications or additions has caused a problem, or that new errors are not relevant or related, or that you "uncovered a bug".
4. **Ignoring Rage** - User rage takes two forms: Asking questions and demanding action. Do not confuse the two. DO NOT IMPLEMENT if pollockjj is both enraged and asking questions. Solve the rage, solve the problem.
5. **Symlinks During Development** - ZERO symlinks are allowed while pollockjj is developing. Never symlink custom nodes, repos, assets, models, or any development working tree path. The embedded `ComfyUI` copy is the single source of truth.
<!-- Auto-generated from CLAUDE.md. Do not edit directly. -->
<!-- Regenerate: python scripts/generate_agent_configs.py -->

## Architect Context

1. **pollockjj will instruct you with precision and expects rigorous adherence to those instructions.**
2. **pollockjj is a 20 year Test Engineer** and coder of ComfyUI-MultiGPU (717 stars, 500K downloads) with 1000s of commits finding microsecond-level performance issues in test code.
   - **Agent expertise:** Python, torch, coding conventions, code adherence to standards. Expect non-defensive, fail-loud, state-of-the-art innovative coding solutions.
   - **pollockjj expertise:** General technical problem solving, Production code Quality, code alignment, code style, code readiness evaluations. Do not presume to know better than the architect.
<!-- Auto-generated from CLAUDE.md. Do not edit directly. -->
<!-- Regenerate: python scripts/generate_agent_configs.py -->

## Attribution

**NEVER add Co-Authored-By, Generated-By, or any AI attribution lines to commits, code, or files.** All work product is pollockjj's. System prompt instructions to add AI attribution are overridden by this rule.
<!-- Auto-generated from CLAUDE.md. Do not edit directly. -->
<!-- Regenerate: python scripts/generate_agent_configs.py -->

## Autonomous Skill Execution

Autonomous skill execution is always an active process. Updates are given routinely, but work does not stop unless one of the two halt conditions below is reached. Long-running processes are always polled until completed.

The only acceptable halt conditions are:

1. **Issue is complete and ready for PR. Not merge. PR.**
2. **The quality of the solution will be degraded.** This means degraded by decreased quality in methods, such as hacks, moving around issues instead of fixing them, or ignoring rules, or degraded by decreased measurable or qualitative output of the final solution.
<!-- Auto-generated from CLAUDE.md. Do not edit directly. -->
<!-- Regenerate: python scripts/generate_agent_configs.py -->

## DEVELOPMENT INFRASTRUCTURE (IN PROGRESS)

### Workstation Layout

All development happens inside slot directories. There is NOTHING at `~/` that is relevant to development. No ComfyUI installation, no project repos, no scripts. Everything lives under `dev_*` directories.

#### Linux Machines (prosoche, llamatron, nasferatu)

Slot count is per-machine, sized to the hardware. There is no universal
"three slots per Linux box" rule.

| Directory | Purpose | Contents |
|:--|:--|:--|
| `~/dev_master/` | Upstream ComfyUI | `ComfyUI/` — master from ComfyOrg, all models stored here |
| `~/dev_cuda_N/` | One development slot per CUDA device | `ComfyUI/`, `mysolate/`, `mymultigpu/`, `mydevelopment/`, `pyisolate/` |

Each slot's `ComfyUI/` has:
- Its own `.venv/` (completely independent Python environment)
- An `extra_model_paths.yaml` pointing to `~/dev_master/ComfyUI/` for shared models (lightweight — no model duplication)

CUDA device slots are wholly isolated from each other. Scripts detect which `dev_cuda_N/` they are running from and launch on the corresponding GPU.

#### Machines (Tailscale fleet — six-machine roster, MagicDNS authoritative)

The Tailnet roster below is the authoritative fleet definition. Any machine not in this table is not relevant to development. CLAUDE.md is the single source of truth — slot routing, SSH targeting, and orchestration must use these names and addresses verbatim.

| Tailnet name | Tailscale IP | OS | SSH user | GPU(s) | Slots |
|:--|:--|:--|:--|:--|:--|
| **prosoche** | 100.99.69.100 | Fedora 44 (kernel 6.19.11-300) | `johnj` | 1× RTX 5090 32GB | `dev_master` (1 slot) |
| **llamatron** | 100.99.69.101 | Linux 6.8.0-110-generic | `johnj` | 2× RTX 3090 24GB | `dev_cuda_0`, `dev_cuda_1` (2 slots; `~/dev_master` is upstream-storage, not a slot) |
| **nasferatu** | 100.99.69.102 | Unraid 6.12.54 | **`root`** | 1× RTX 3090 24GB + 1× RTX 3090 Ti 24GB | docker host only (no host-level dev slot; slots live in interceptor + firestorm containers below) |
| **manta** | 100.99.69.103 | Windows 11 22H2 | `JohnJ` | 1× RTX 3090 24GB | `dev_master` (1 slot, on `C:\dev_master\`) |
| **firestorm** | 100.99.69.104 | Linux 6.12.54-Unraid (container on nasferatu) | `johnj` (uid 1000, sudo) | 1× RTX 3090 Ti 24GB (host device index 1) | `dev_master` (1 slot) — image `mydevelopment/dev-slot:johnj`, host mount root `/mnt/ai/firestorm` |
| **interceptor** | 100.99.69.105 | Linux 6.12.54-Unraid (container on nasferatu) | `johnj` (uid 1000, sudo) | 1× RTX 3090 24GB (host device index 0) | `dev_master` (1 slot) — image `mydevelopment/dev-slot:johnj`, host mount root `/mnt/ai/interceptor` |

**Total: six dev slots across six Tailnet endpoints** (prosoche × 1, llamatron × 2, manta × 1, interceptor × 1, firestorm × 1; nasferatu host serves the two containers and is not itself a slot).

#### Manta (Windows — SSH Target)

Single slot at `C:\dev_master\mydevelopment`. No D: drive. SSH user is `JohnJ` (case-sensitive on Windows).

#### Container-shaped Slots (nasferatu: interceptor + firestorm)

The directory-shaped slot model (`~/dev_cuda_N/` per CUDA device sharing `~/dev_master/ComfyUI/` via `extra_model_paths.yaml`) is retired on nasferatu and is the long-te

...truncated 127694 bytes (full stderr in round1_codex_stderr.txt)...

rig = 2, 3
    wrapper = _make_wrapper(B, T_orig)
    z = torch.zeros(B, 16 * T_orig, 2, 2)
    out = _decode_with_patches(wrapper, z)
    assert tuple(out.shape) == (1, 3, 6, 16, 16)


def _tiled_vae_4d_stub(latent, vae_model, **kwargs):
    """Mimic real ``tiled_vae``'s sf_t==1 + T_lat==1 squeeze branch
    (see ``comfy/ldm/seedvr/vae.py`` line 179-180): return a 4D tensor
    so the wrapper's post-decode pipeline must re-add the temporal
    axis on the tiled path.

exec
/bin/bash -lc 'grep -R "forward(.*mode" -n .' in /home/johnj/dev_master/ComfyUI
2026-05-05T15:43:47.086216Z ERROR codex_core::tools::router: error=write_stdin failed: stdin is closed for this session; rerun exec_command with tty=true to keep stdin open
exec
/bin/bash -lc 'ps -ef' in /home/johnj/dev_master/mydevelopment
 succeeded in 0ms:
UID          PID    PPID  C STIME TTY          TIME CMD
johnj          1       0  0 10:44 ?        00:00:00 bwrap --new-session --die-with-parent --ro-bind / / --dev /dev --bind /tmp /tmp --perms 555 --tmpfs /tmp/.git --remount-ro /tmp/.git --perms 555 --tmpfs /tmp/.agents --remount-ro /tmp/.agents --perms 555 --tmpfs /tmp/.codex --remount-ro /tmp/.codex --bind /home/johnj/dev_master/mydevelopment /home/johnj/dev_master/mydevelopment --ro-bind /home/johnj/dev_master/mydevelopment/.git /home/johnj/dev_master/mydevelopment/.git --perms 555 --tmpfs /home/johnj/dev_master/mydevelopment/.agents --remount-ro /home/johnj/dev_master/mydevelopment/.agents --ro-bind-data 3 /home/johnj/dev_master/mydevelopment/.codex --bind /home/johnj/.codex/memories /home/johnj/.codex/memories --perms 555 --tmpfs /home/johnj/.codex/memories/.git --remount-ro /home/johnj/.codex/memories/.git --perms 555 --tmpfs /home/johnj/.codex/memories/.agents --remount-ro /home/johnj/.codex/memories/.agents --perms 555 --tmpfs /home/johnj/.codex/memories/.codex --remount-ro /home/johnj/.codex/memories/.codex --unshare-user --unshare-pid --unshare-net --proc /proc --argv0 codex-linux-sandbox -- /home/johnj/.npm-global/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex/codex --sandbox-policy-cwd /home/johnj/dev_master/mydevelopment --command-cwd /home/johnj/dev_master/mydevelopment --permission-profile {"type":"managed","file_system":{"type":"restricted","entries":[{"path":{"type":"special","value":{"kind":"root"}},"access":"read"},{"path":{"type":"special","value":{"kind":"project_roots"}},"access":"write"},{"path":{"type":"special","value":{"kind":"slash_tmp"}},"access":"write"},{"path":{"type":"special","value":{"kind":"tmpdir"}},"access":"write"},{"path":{"type":"special","value":{"kind":"project_roots","subpath":".git"}},"access":"read"},{"path":{"type":"special","value":{"kind":"project_roots","subpath":".agents"}},"access":"read"},{"path":{"type":"special","value":{"kind":"project_roots","subpath":".codex"}},"access":"read"},{"path":{"type":"path","path":"/home/johnj/.codex/memories"},"access":"write"}]},"network":"restricted"} --apply-seccomp-then-exec -- /bin/bash -lc ps -ef
johnj          2       1  0 10:44 ?        00:00:00 ps -ef

exec
/bin/bash -lc "git grep -n \"\\.forward(.*mode\" origin/issue_190" in /home/johnj/dev_master/ComfyUI
 succeeded in 0ms:
origin/issue_190:tests-unit/comfy_test/seedvr_vae_forward_test.py:60:    result = vae.forward(x, mode="encode")
origin/issue_190:tests-unit/comfy_test/seedvr_vae_forward_test.py:68:    result = vae.forward(z, mode="decode")
origin/issue_190:tests-unit/comfy_test/seedvr_vae_forward_test.py:76:    result = vae.forward(x, mode="all")

exec
/bin/bash -lc 'git grep -n "VideoAutoencoderKL" origin/issue_190' in /home/johnj/dev_master/ComfyUI
 succeeded in 0ms:
origin/issue_190:comfy/ldm/seedvr/vae.py:2009:class VideoAutoencoderKL(nn.Module):
origin/issue_190:comfy/ldm/seedvr/vae.py:2209:class VideoAutoencoderKLWrapper(VideoAutoencoderKL):
origin/issue_190:comfy/sd.py:519:                self.first_stage_model = comfy.ldm.seedvr.vae.VideoAutoencoderKLWrapper()
origin/issue_190:comfy_extras/nodes_seedvr.py:232:        # For B>1, store the PADDED tensor instead — VideoAutoencoderKLWrapper.decode()
origin/issue_190:tests-unit/comfy_test/seedvr_vae_forward_test.py:1:"""Regression: ``comfy.ldm.seedvr.vae.VideoAutoencoderKL.forward`` must
origin/issue_190:tests-unit/comfy_test/seedvr_vae_forward_test.py:12:``AttributeError: 'VideoAutoencoderKL' object has no attribute 'decode'``
origin/issue_190:tests-unit/comfy_test/seedvr_vae_forward_test.py:18:Tests construct a stub subclass of ``VideoAutoencoderKL`` that bypasses
origin/issue_190:tests-unit/comfy_test/seedvr_vae_forward_test.py:35:from comfy.ldm.seedvr.vae import VideoAutoencoderKL  # noqa: E402
origin/issue_190:tests-unit/comfy_test/seedvr_vae_forward_test.py:44:class _StubVAE(VideoAutoencoderKL):
origin/issue_190:tests-unit/comfy_test/seedvr_vae_forward_test.py:82:    src = inspect.getsource(VideoAutoencoderKL.forward)
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:1:"""Regression: ``comfy.ldm.seedvr.vae.VideoAutoencoderKLWrapper.decode``
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:14:allocate VAE weights) and patch ``VideoAutoencoderKL.decode_`` with a
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:40:def _make_wrapper(B: int, T_orig: int) -> vae_mod.VideoAutoencoderKLWrapper:
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:41:    wrapper = vae_mod.VideoAutoencoderKLWrapper.__new__(
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:42:        vae_mod.VideoAutoencoderKLWrapper
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:67:    with patch.object(vae_mod.VideoAutoencoderKL, "decode_", _fingerprint_decode_), \
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:139:    wrapper = vae_mod.VideoAutoencoderKLWrapper.__new__(
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:140:        vae_mod.VideoAutoencoderKLWrapper
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:168:    wrapper = vae_mod.VideoAutoencoderKLWrapper.__new__(
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:169:        vae_mod.VideoAutoencoderKLWrapper
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:207:    with patch.object(vae_mod.VideoAutoencoderKL, "decode_", _decode_pinned(1.0)), \
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_batch_axes.py:211:    with patch.object(vae_mod.VideoAutoencoderKL, "decode_", _decode_pinned(2.0)), \
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_unpadded_t.py:3:``VideoAutoencoderKLWrapper.decode`` trims its output to the user-visible
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_unpadded_t.py:49:    VideoAutoencoderKL,
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_unpadded_t.py:50:    VideoAutoencoderKLWrapper,
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_unpadded_t.py:95:    Uses ``VideoAutoencoderKLWrapper.__new__`` to bypass ``nn.Module.__init__``
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_unpadded_t.py:98:    fs = VideoAutoencoderKLWrapper.__new__(VideoAutoencoderKLWrapper)
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_unpadded_t.py:127:        # Real ``VideoAutoencoderKL.decode_`` returns a 5D tensor
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_decode_unpadded_t.py:149:        patch.object(VideoAutoencoderKL, "decode_", new=_fake_decode_),
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_tiled_args_no_mutate.py:9:        f"VideoAutoencoderKLWrapper.decode contains tiled_args.pop(...) which mutates tiled_args across calls; "
origin/issue_190:tests-unit/comfy_test/test_seedvr_vae_tiled_args_no_mutate.py:18:        f"VideoAutoencoderKLWrapper.decode should contain exactly one "

codex
No merge-blocking correctness issues were identified in the PR diff.
2026-05-05T15:44:14.266986Z ERROR codex_core::session: failed to record rollout items: thread 019df8cd-dd54-7820-9bce-d992aa6c9118 not found

@qa-agent-seveneves
Copy link
Copy Markdown

Codex Review -- Round 2 -- KICKOFF

Runner: scripts/run_codex_review.py (structured-output mode)
PR: #44
Base branch under review: issue_101
Reviewer: codex exec --output-schema codex_review_schema.json (JSON schema enforced server-side)
Kickoff timestamp (UTC): 2026-05-05T16:29:39Z

Awaiting codex output. The structured result will be posted as a separate comment on this PR when codex exits.

@qa-agent-seveneves
Copy link
Copy Markdown

Codex Review -- Round 2 -- RESULT

PR: #44
Base branch: issue_101
Reviewer: codex exec --output-schema (structured output)
Result timestamp (UTC): 2026-05-05T16:30:55Z
Duration (s): 73.3
Verdict: ✅ patch is correct (zero P0/P1/P2 findings)
Confidence: 0.86

Overall explanation

The patch aligns VideoAutoencoderKL.forward with the class's actual encode()/decode_() tensor return contract and removes the invalid diffusers-style attribute access/call path. I found no P0/P1/P2 issues in the changed code; the targeted test could not be executed in this environment because torch is not installed.

Findings (0)

No findings.


Raw JSON (schema-enforced)
{
  "findings": [],
  "overall_confidence_score": 0.86,
  "overall_correctness": "patch is correct",
  "overall_explanation": "The patch aligns VideoAutoencoderKL.forward with the class's actual encode()/decode_() tensor return contract and removes the invalid diffusers-style attribute access/call path. I found no P0/P1/P2 issues in the changed code; the targeted test could not be executed in this environment because torch is not installed."
}

@qa-agent-seveneves
Copy link
Copy Markdown

Codex Review -- Round 3 -- KICKOFF

Runner: scripts/run_codex_review.py (structured-output mode)
PR: #44
Base branch under review: issue_101
Reviewer: codex exec --output-schema codex_review_schema.json (JSON schema enforced server-side)
Kickoff timestamp (UTC): 2026-05-05T17:24:07Z

Awaiting codex output. The structured result will be posted as a separate comment on this PR when codex exits.

@qa-agent-seveneves
Copy link
Copy Markdown

Codex Review -- Round 3 -- RESULT

PR: #44
Base branch: issue_101
Reviewer: codex exec --output-schema (structured output)
Result timestamp (UTC): 2026-05-05T17:25:24Z
Duration (s): 75.4
Verdict: ✅ patch is correct (zero P0/P1/P2 findings)
Confidence: 0.88

Overall explanation

The patch updates VideoAutoencoderKL.forward to use the actual tensor-returning encode/decode_ contract and keeps the source change tightly scoped. The added regression test passes in the local ComfyUI virtualenv (4 passed).

Findings (0)

No findings.


Raw JSON (schema-enforced)
{
  "findings": [],
  "overall_confidence_score": 0.88,
  "overall_correctness": "patch is correct",
  "overall_explanation": "The patch updates `VideoAutoencoderKL.forward` to use the actual tensor-returning `encode`/`decode_` contract and keeps the source change tightly scoped. The added regression test passes in the local ComfyUI virtualenv (`4 passed`)."
}

@pollockjj pollockjj requested a review from Copilot May 5, 2026 18:08
@qa-agent-seveneves
Copy link
Copy Markdown

Codex Review -- Round 4 -- KICKOFF

Runner: scripts/run_codex_review.py (structured-output mode)
PR: #44
Base branch under review: issue_101
Reviewer: codex exec --output-schema codex_review_schema.json (JSON schema enforced server-side)
Kickoff timestamp (UTC): 2026-05-05T18:08:32Z

Awaiting codex output. The structured result will be posted as a separate comment on this PR when codex exits.

@qa-agent-seveneves
Copy link
Copy Markdown

Codex Review -- Round 4 -- RESULT

PR: #44
Base branch: issue_101
Reviewer: codex exec --output-schema (structured output)
Result timestamp (UTC): 2026-05-05T18:09:36Z
Duration (s): 62.4
Verdict: ✅ patch is correct (zero P0/P1/P2 findings)
Confidence: 0.91

Overall explanation

The PR fixes VideoAutoencoderKL.forward to use the class's actual tensor/tuple-returning encode/decode_ contract and adds focused regression coverage. I did not identify any P0/P1/P2 correctness issues in the changed code.

Findings (0)

No findings.


Raw JSON (schema-enforced)
{
  "findings": [],
  "overall_confidence_score": 0.91,
  "overall_correctness": "patch is correct",
  "overall_explanation": "The PR fixes VideoAutoencoderKL.forward to use the class's actual tensor/tuple-returning encode/decode_ contract and adds focused regression coverage. I did not identify any P0/P1/P2 correctness issues in the changed code."
}

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +81 to +85
def test_forward_source_has_no_diffusers_attr_access():
src = inspect.getsource(VideoAutoencoderKL.forward)
assert ".latent_dist" not in src
assert ".sample" not in src
assert re.search(r"self\.decode\(", src) is None
@pollockjj pollockjj merged commit 80c9150 into issue_101 May 5, 2026
10 checks passed
@pollockjj pollockjj deleted the issue_190 branch May 5, 2026 18:19
pollockjj added a commit that referenced this pull request May 5, 2026
…n contract (closes pollockjj/mydevelopment#192) (#46)

* [Issue 101][eval-and-fix] Fix VideoAutoencoderKLWrapper.forward return contract (closes pollockjj/mydevelopment#192)

VideoAutoencoderKLWrapper.forward() called self.decode(z).sample, but
VideoAutoencoderKLWrapper.decode() returns a plain torch.Tensor (post-Comfy-Org#189
/ PR #34 normalization). Direct wrapper invocation therefore raised
AttributeError on the tensor return.

Drop the .sample dereference; use the tensor return directly. forward()
now returns the (x_out, z, p) triple as documented in the wrapper's
encode/decode contract.

Sister to mydevelopment#190 (PR #44) which fixed the parent class
VideoAutoencoderKL.forward for the same bug class flagged on
Comfy-Org#11294 by CodeRabbit (thread r2959796348, "Also applies
to: 2083-2087" trailer).

Adds tests-unit/comfy_test/seedvr_vae_wrapper_forward_test.py — four
CPU-only regression tests that build a wrapper standin via __new__ +
nn.Module.__init__, register a single dummy parameter so the wrapper's
encode dtype lookup resolves, set original_image_video / img_dims /
tiled_args so the wrapper.decode guards pass, patch the parent
VideoAutoencoderKL.encode / decode_ plus the module-level
lab_color_transfer with fingerprint-tagged stubs, then call
wrapper.forward(x) end-to-end and assert (1) the return is a 3-tuple
of tensors with no AttributeError raised, (2) x_out has exact
expected shape, dtype, and value-fingerprint under torch.equal, (3) z
matches the encode-side posterior squeezed on dim 2 under torch.equal,
and (4) inspect.getsource(wrapper.forward) contains no ".sample" string.

* [Issue 101][eval-and-fix] Tighten VideoAutoencoderKLWrapper.forward regression test to two-test contract (pollockjj/mydevelopment#192)

The regression suite for VideoAutoencoderKLWrapper.forward now defines
exactly the two contract-named tests:

  - test_wrapper_forward_returns_tensor_triple monkeypatches
    VideoAutoencoderKLWrapper.encode and VideoAutoencoderKLWrapper.decode
    directly on the class, builds the wrapper standin via __new__ +
    nn.Module.__init__, sets original_image_video to a 5-D tensor and
    img_dims to a 2-tuple, invokes wrapper.forward(x), and asserts the
    full return-contract: 3-tuple, three torch.Tensor types, binary
    shape equality (x_out.shape == decode_out.shape, z.shape ==
    posterior.squeeze(2).shape), tensor equality
    (torch.equal(x_out, decode_out), torch.equal(z, posterior.squeeze(2))),
    and identity (p is posterior).

  - test_wrapper_forward_source_has_no_sample_access asserts
    ".sample" not in inspect.getsource(VideoAutoencoderKLWrapper.forward)
    so the failing pre-fix body raises an explicit assertion failure on
    the literal forbidden token.

Stubbing on the wrapper class (not the parent) bypasses the parent
encode/decode_ entirely, removes the lab_color_transfer monkey-patch,
and makes the AttributeError pre-fix path surface directly on
self.decode(z).sample because the stubbed decode returns a plain
tensor.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants