Conversation
|
✅ All contributors have signed the CLA. Thank you! This PR is ready to be merged. |
|
Reviewer speedkit — workflow + exhibits API-format workflow, image → 2.1 shape → paint → textured GLB (native nodes only). Weights: {
"1": {
"class_type": "LoadImage",
"inputs": {
"image": "reference.png"
}
},
"2": {
"class_type": "LoadBackgroundRemovalModel",
"inputs": {
"bg_removal_name": "birefnet.safetensors"
}
},
"3": {
"class_type": "RemoveBackground",
"inputs": {
"bg_removal_model": [
"2",
0
],
"image": [
"1",
0
]
}
},
"4": {
"class_type": "EmptyImage",
"inputs": {
"width": 1024,
"height": 1024,
"batch_size": 1,
"color": 16777215
}
},
"5": {
"class_type": "ImageCompositeMasked",
"inputs": {
"destination": [
"4",
0
],
"source": [
"1",
0
],
"mask": [
"3",
0
],
"x": 0,
"y": 0,
"resize_source": true
}
},
"6": {
"class_type": "ImageOnlyCheckpointLoader",
"inputs": {
"ckpt_name": "hunyuan_3d_v2.1.safetensors"
}
},
"7": {
"class_type": "ModelSamplingAuraFlow",
"inputs": {
"model": [
"6",
0
],
"shift": 1.0
}
},
"8": {
"class_type": "CLIPVisionEncode",
"inputs": {
"clip_vision": [
"6",
1
],
"image": [
"5",
0
],
"crop": "center"
}
},
"9": {
"class_type": "Hunyuan3Dv2Conditioning",
"inputs": {
"clip_vision_output": [
"8",
0
]
}
},
"10": {
"class_type": "EmptyLatentHunyuan3Dv2",
"inputs": {
"resolution": 4096,
"batch_size": 1
}
},
"11": {
"class_type": "KSampler",
"inputs": {
"model": [
"7",
0
],
"positive": [
"9",
0
],
"negative": [
"9",
1
],
"latent_image": [
"10",
0
],
"seed": 42,
"steps": 30,
"cfg": 5.0,
"sampler_name": "euler",
"scheduler": "normal",
"denoise": 1.0
}
},
"12": {
"class_type": "VAEDecodeHunyuan3D",
"inputs": {
"samples": [
"11",
0
],
"vae": [
"6",
2
],
"num_chunks": 8000,
"octree_resolution": 256
}
},
"13": {
"class_type": "VoxelToMesh",
"inputs": {
"voxel": [
"12",
0
],
"algorithm": "surface net",
"threshold": 0.6
}
},
"14": {
"class_type": "Hunyuan3DPaintModelLoader",
"inputs": {
"model_name": "hunyuan3d-paintpbr-v2-1.safetensors"
}
},
"15": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "hunyuan3d_paintpbr_v2_1_vae.safetensors"
}
},
"16": {
"class_type": "Hunyuan3DPaintConditioning",
"inputs": {
"model": [
"14",
0
],
"vae": [
"15",
0
],
"mesh": [
"13",
0
],
"reference_image": [
"5",
0
],
"num_views": 6,
"resolution": 512
}
},
"17": {
"class_type": "KSampler",
"inputs": {
"model": [
"16",
0
],
"positive": [
"16",
1
],
"negative": [
"16",
2
],
"latent_image": [
"16",
3
],
"seed": 42,
"steps": 20,
"cfg": 6.0,
"sampler_name": "euler",
"scheduler": "sgm_uniform",
"denoise": 1.0
}
},
"18": {
"class_type": "Hunyuan3DPaintSplitLatent",
"inputs": {
"model": [
"16",
0
],
"samples": [
"17",
0
]
}
},
"19": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"18",
0
],
"vae": [
"15",
0
]
}
},
"20": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"18",
1
],
"vae": [
"15",
0
]
}
},
"21": {
"class_type": "Hunyuan3DBakeMultiView",
"inputs": {
"mesh": [
"13",
0
],
"albedo": [
"19",
0
],
"mr": [
"20",
0
],
"cameras": [
"16",
4
],
"texture_size": 2048
}
},
"22": {
"class_type": "SaveGLB",
"inputs": {
"mesh": [
"21",
0
],
"filename_prefix": "3d/hunyuan3d_painted"
}
}
}Exhibits (same seed 42, 6 views / 512 px / 20 steps / cfg 6.0, ~72 s and 8.6 GiB peak on an RTX 5060 Ti 16 GB) are embedded in the PR description above. |
|
I have read and agree to the Contributor License Agreement |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Hunyuan3D 2.1 paint support with a native 2.5D UNet, specialized attention, checkpoint loading, packed latent handling, and ComfyUI nodes. Adds torch-based multiview rendering, UV baking, hole filling, and coordinate-convention documentation. Extends mesh and GLB handling for metallic-roughness textures. Adds deterministic model, renderer, convention, sampling, and reference-parity tests with supporting bundle and comparison tools. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@comfy/ldm/hunyuan3d/paint/attention.py`:
- Line 13: Remove the einops.rearrange import and replace every rearrange use in
comfy/ldm/hunyuan3d/paint/attention.py (including the operations around lines
187-188, 208, and 219) with equivalent native tensor operations while preserving
shapes and ordering. Apply the same change in comfy/ldm/hunyuan3d/paint/unet.py
(including lines 203-205, 231-236, 649-652, and 696-697), removing its import
and using reshape, view, permute, transpose, flatten, or equivalent methods; no
direct changes are needed elsewhere.
- Around line 265-266: Remove the `@torch.no_grad`() decorators from
_mean_voxel_indices and multires_voxel_indices in
comfy/ldm/hunyuan3d/paint/attention.py and from compute_reference_bank in
comfy/ldm/hunyuan3d/paint/unet.py. Do not replace them with other inference-mode
wrappers.
In `@comfy/ldm/hunyuan3d/paint/render.py`:
- Around line 490-495: In the rendering function containing the `for vi in
range(V)` loop, add an upfront validation that the number of camera elevations
and azimuths matches `views.shape[0]` (`V`), raising a clear validation error
when counts differ. Ensure the check handles both too few and too many camera
views before indexing `cameras.elevs[vi]` and `cameras.azims[vi]`, while leaving
the existing weight fallback unchanged.
- Around line 119-131: Update view_matrix() to detect when the normalized lookat
direction is parallel or near-parallel to the fixed Z-up vector, and use a
non-parallel fallback up axis for those pole views before computing right.
Preserve the existing Z-up behavior for all other camera directions so
STANDARD_VIEW_ELEVS, including ±90°, produces finite matrices.
In `@tests-unit/comfy_test/paint_parity/bundle_format.py`:
- Around line 84-86: Update the key-processing loop in the bundle parity
comparison to validate each requested key exists in both reference and candidate
captures before indexing them. When a key is absent, raise a descriptive error
identifying the missing key and capture side, rather than allowing a raw
KeyError; preserve normal float comparison for keys present in both.
In `@tests-unit/comfy_test/paint_parity/capture_reference.py`:
- Around line 88-90: Always pass the CPU patch that removes the hard-coded
.to("cuda:0") move when loading attn_processor.py in the capture path; do not
condition it on torch.cuda.is_available(). Keep the existing load_module calls
and reference module loading unchanged.
- Around line 96-103: In the model-loading fallback around
UNet2p5DConditionModel.from_pretrained, only handle the specific TypeError
caused by unsupported private config keys. Inspect the exception details and
re-raise unrelated TypeErrors instead of entering the from_config fallback,
preserving the existing alternate construction path for the known mismatch.
In `@tests-unit/comfy_test/paint_parity/harness.py`:
- Around line 44-48: Remove locally forced no-grad execution from the parity
paths: in tests-unit/comfy_test/paint_parity/harness.py lines 44-48, initialize
parameters through detached tensors such as p.detach().copy_(...) without
changing ambient mode; in harness.py lines 92-101, let the native forward use
the caller’s execution context; and in
tests-unit/comfy_test/paint_parity/capture_reference.py lines 141-152, likewise
remove the local no-grad wrapper around reference execution.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: baaab730-b2bd-4698-890b-cff23e821f45
📒 Files selected for processing (26)
comfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/CONVENTIONS.mdcomfy/ldm/hunyuan3d/paint/__init__.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/unet.pycomfy/model_base.pycomfy/model_detection.pycomfy/supported_models.pycomfy_api/latest/_util/geometry_types.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy_extras/nodes_save_3d.pynodes.pytests-unit/comfy_test/paint_parity/README.mdtests-unit/comfy_test/paint_parity/__init__.pytests-unit/comfy_test/paint_parity/bundle_format.pytests-unit/comfy_test/paint_parity/capture_reference.pytests-unit/comfy_test/paint_parity/compare_reference.pytests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensorstests-unit/comfy_test/paint_parity/harness.pytests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/test_hunyuan3d_paint_render.py
📜 Review details
⚠️ CI failures not shown inline (2)
GitHub Actions: CLA Assistant / 0_cla-assistant.txt: Add native Hunyuan3D 2.1 PBR paint (mesh -> multiview -> textured GLB)
Conclusion: failure
##[group]Run contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08
with:
path-to-document: https://github.com/Comfy-Org/comfy-cla/blob/main/comfyui_icla.md
remote-organization-name: comfy-org
remote-repository-name: comfy-cla
path-to-signatures: signatures/cla.json
branch: main
allowlist: action@github.com,actions-user,ampagent,claude,comfy-pr-bot,GitHub Action,github-actions,github-actions[bot],Glary Bot,Glary-Bot,*[bot]
custom-notsigned-prcomment: 🎉 Thank you for your contribution, we really appreciate it! 🎉
Like many open source projects, we require contributors to sign our [Contributor License Agreement (CLA)](https://github.com/Comfy-Org/comfy-cla/blob/main/comfyui_icla.md). A CLA makes the ownership of contributions explicit, so contributors and the project share a clear understanding of how the code can be used. By signing, you:
- Confirm that you own your contribution.
- Keep the right to reuse your own code.
- Grant us a copyright license to include and share it within our projects.
CLAs are standard practice across major open source projects including those under the Apache Software Foundation and the Linux Foundation. Ours is based on the Apache Software Foundation's CLA. Most importantly, it would enable us to relicense the project under a more permissive license in the future, giving the project and its community greater flexibility.
✍ **To sign, please post a new comment on this PR with exactly the following text:** ✍
custom-pr-sign-comment: I have read and agree to the Contributor License Agreement
custom-allsigned-prcomment: ✅ All contributors have signed the CLA. Thank you! This PR is ready to be merged.
use-dco-flag: false
lock-pullrequest-aftermerge: true
suggest-recheck: true
env:
GITHUB_***REDACTED***
PERSONAL_ACCESS_***REDACTED***
##[endgroup]
CLA Assistant GitHub Action bot has started the process
(node:2138) [DEP0040] DeprecationWarning: The `punycode` module is deprec...
GitHub Actions: CLA Assistant / cla-assistant: Add native Hunyuan3D 2.1 PBR paint (mesh -> multiview -> textured GLB)
Conclusion: failure
##[group]Run contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08
with:
path-to-document: https://github.com/Comfy-Org/comfy-cla/blob/main/comfyui_icla.md
remote-organization-name: comfy-org
remote-repository-name: comfy-cla
path-to-signatures: signatures/cla.json
branch: main
allowlist: action@github.com,actions-user,ampagent,claude,comfy-pr-bot,GitHub Action,github-actions,github-actions[bot],Glary Bot,Glary-Bot,*[bot]
custom-notsigned-prcomment: 🎉 Thank you for your contribution, we really appreciate it! 🎉
Like many open source projects, we require contributors to sign our [Contributor License Agreement (CLA)](https://github.com/Comfy-Org/comfy-cla/blob/main/comfyui_icla.md). A CLA makes the ownership of contributions explicit, so contributors and the project share a clear understanding of how the code can be used. By signing, you:
- Confirm that you own your contribution.
- Keep the right to reuse your own code.
- Grant us a copyright license to include and share it within our projects.
CLAs are standard practice across major open source projects including those under the Apache Software Foundation and the Linux Foundation. Ours is based on the Apache Software Foundation's CLA. Most importantly, it would enable us to relicense the project under a more permissive license in the future, giving the project and its community greater flexibility.
✍ **To sign, please post a new comment on this PR with exactly the following text:** ✍
custom-pr-sign-comment: I have read and agree to the Contributor License Agreement
custom-allsigned-prcomment: ✅ All contributors have signed the CLA. Thank you! This PR is ready to be merged.
use-dco-flag: false
lock-pullrequest-aftermerge: true
suggest-recheck: true
env:
GITHUB_***REDACTED***
PERSONAL_ACCESS_***REDACTED***
##[endgroup]
CLA Assistant GitHub Action bot has started the process
(node:2138) [DEP0040] DeprecationWarning: The `punycode` module is deprec...
🧰 Additional context used
📓 Path-based instructions (7)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Keep changes small, direct, and limited to the narrowest code path and fewest files necessary; prefer practical fixes over broad architectural work.
Prefer fewer dependencies and do not add a ComfyUI dependency unless absolutely necessary.
Remove obsolete code, dead branches, unused options, debug prints, and unnecessary compatibility paths.
Preserve existing APIs, node names, model-loading behavior, file layout, and workflow compatibility unless replacement is explicit.
Keep architectural layers focused; do not leak UI, API, workflow, queue, persistence, telemetry, model-loading, node, or execution concerns into unrelated layers.
Shared core modules should depend only on lower-level primitives and their own domain concepts; higher-level concepts belong at callers, adapters, services, or boundaries.
Pass only the narrowest data needed across boundaries and keep identity mapping, persistence, history, telemetry, response shaping, and UI state in their owning layers.
Before touching many files, identify the smallest owner layer; use caller-side mappings, adapters, events, or narrow interfaces instead of exposing private concepts across layers.
Core ComfyUI code must not make unsolicited internet requests or add uploads, telemetry, analytics, tracking, reporting, update checks, remote configuration, licensing checks, or similar outbound paths.
Model downloading is allowed only when explicitly authorized by the user, limited to the requested artifact, and free of telemetry, tracking, unrelated metadata, or background activity.
Warning and info messages should be short and actionable; documentation and README changes should be concise, factual, and tied to changed behavior.
Use short direct commit subjects such asFix ...,Add ...,Support ...,Remove ..., orUpdate ...; keep PR descriptions short and state the problem, behavior change, and tests.
Prefer one coherent behavioral change per commit and prioritize crashes, incorrect dtype/device behavior, m...
Files:
comfy/ldm/hunyuan3d/paint/CONVENTIONS.mdtests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pytests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensorstests-unit/comfy_test/paint_parity/README.mdnodes.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pycomfy/model_detection.pytests-unit/comfy_test/paint_parity/harness.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/loader.pytests-unit/comfy_test/paint_parity/capture_reference.pycomfy/latent_formats.pytests-unit/comfy_test/paint_parity/bundle_format.pycomfy_extras/nodes_save_3d.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/ldm/hunyuan3d/paint/attention.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/unet.pytests-unit/comfy_test/test_hunyuan3d_paint.py
**
⚙️ CodeRabbit configuration file
**: IMPORTANT: Only comment on issues directly introduced by this PR's code changes.
Treat AGENTS.md as mandatory repository policy, not optional style guidance.
Flag PR changes that violate AGENTS.md even when the code is otherwise functional.
In particular, enforce architecture boundaries, dtype/device/memory rules,
interface contracts, import style, no unnecessary try/except blocks, no inline
imports, no outbound internet paths in core ComfyUI, and narrow scoped fixes.
Prefer direct findings over suggestions when a rule is violated. Only ignore
AGENTS.md when it clearly conflicts with a newer explicit maintainer instruction
in the PR.
Do NOT flag pre-existing issues in code that was merely moved, re-indented,
de-indented, or reformatted without logic changes. If code appears in the diff
only due to whitespace or structural reformatting (e.g., removing awith:block),
treat it as unchanged. Contributors should not feel obligated to address
pre-existing issues outside the scope of their contribution.
Files:
comfy/ldm/hunyuan3d/paint/CONVENTIONS.mdtests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pytests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensorstests-unit/comfy_test/paint_parity/README.mdnodes.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pycomfy/model_detection.pytests-unit/comfy_test/paint_parity/harness.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/loader.pytests-unit/comfy_test/paint_parity/capture_reference.pycomfy/latent_formats.pytests-unit/comfy_test/paint_parity/bundle_format.pycomfy_extras/nodes_save_3d.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/ldm/hunyuan3d/paint/attention.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/unet.pytests-unit/comfy_test/test_hunyuan3d_paint.py
comfy/**
⚙️ CodeRabbit configuration file
comfy/**: Core ML/diffusion engine. Focus on:
- Backward compatibility (breaking changes affect all custom nodes)
- Memory management and GPU resource handling
- Performance implications in hot paths
- Thread safety for concurrent execution
Files:
comfy/ldm/hunyuan3d/paint/CONVENTIONS.mdcomfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pycomfy/model_detection.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/unet.py
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Keep state and capability flags on the object that owns the behavior; use explicit parent-owned fields rather than probing children withgetattrfor parent control flow.
Keep public methods aligned with caller contracts; preserve arguments, parameter order, return types, side effects, and error behavior unless all affected interfaces are intentionally updated.
Do not add unused compatibility parameters, flags, attributes, constructor options, or model-specific options to shared helpers.
Normalize third-party and upstream return conventions at integration boundaries so core code receives the expected type and shape.
Avoid caller-side unwrapping such asout = out[0]unless the called interface documents that return structure.
Do not addtorch.no_grad,torch.inference_mode, or inference-mode wrappers; only disable a globally enabled inference mode when a training path requires gradients.
Do not add freeze, unfreeze, or trainability toggles to ComfyUI model classes.
Remove training-only behavior such as dropout from inference models while preserving checkpoint and state-dict compatibility, usingnn.Identitywhen necessary to retain slots.
Keep imports at module scope; use inline imports only for established optional-backend probes or import-cycle avoidance.
Usetry/exceptonly for optional dependency, platform, or backend detection with a useful fallback, and prefer specific exception types.
Do not add code for unsupported pinned library versions or obsolete PyTorch workarounds; unsupported formats, quantization metadata, and bad states should fail clearly.
Match local file style and keep comments sparse, useful, and non-obvious; remove comments that merely restate code.
Files:
tests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pynodes.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pycomfy/model_detection.pytests-unit/comfy_test/paint_parity/harness.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/loader.pytests-unit/comfy_test/paint_parity/capture_reference.pycomfy/latent_formats.pytests-unit/comfy_test/paint_parity/bundle_format.pycomfy_extras/nodes_save_3d.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/ldm/hunyuan3d/paint/attention.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/unet.pytests-unit/comfy_test/test_hunyuan3d_paint.py
comfy/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
comfy/**/*.py: Treat dtype, device placement, VRAM use, offloading, and memory behavior as correctness concerns; use existing ComfyUI quantization, memory, offload, and optimized-operation helpers.
Prefer shared optimized kernels, backend dispatchers, and documented interfaces over duplicate handwritten operations; treat selected backend callables as opaque.
Do not duplicate operations with custom float32-upcasting inference kernels; use generic ComfyUI operations or native PyTorch operations.
If a model constructor has anoperationsparameter, assume it is neverNone; do not add fallback torch operations.
Avoid unnecessary parameters in model, block, and operation constructors or forwards; reuse existing model classes, blocks, operations, and helpers.
Model detectors must inspect only the first dimension of linear weights, guard every dereferenced state-dict key, and order specific signatures before broad fallbacks.
Avoideinopsin core inference code; use native tensor operations such asreshape,view,permute,transpose,flatten, and related methods.
Keep metadata, counters, shape calculations, indices, split boundaries, and control-flow values as Python values rather than tensors.
Avoid unnecessary casts and transfers; preserve intended compute and storage dtypes, tensor shapes, and backend result contracts.
Keep model-native latent layout handling inside the model or latent-format owner rather than reshaping it in nodes or caller-side adapters.
DiT models must pad every patchified target or reference input withcomfy.ldm.common_dit.pad_to_patch_sizeand crop only the target output back to its original dimensions.
Do not add defensive shape, configuration, or dtype casts that merely obscure a clear tensor-operation failure; validate only at meaningful boundaries.
Raw parameters not owned by an operation should be cast at use withcomfy.ops.cast_to_inputorcomfy.model_management.cast_to; model constructors should not contain dtype workaro...
Files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pycomfy/model_detection.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/unet.py
nodes.py
⚙️ CodeRabbit configuration file
nodes.py: Core node definitions (2500+ lines). Focus on:
- Backward compatibility of NODE_CLASS_MAPPINGS
- Consistency of INPUT_TYPES return format
Files:
nodes.py
comfy_extras/**
⚙️ CodeRabbit configuration file
comfy_extras/**: Community-contributed extra nodes. Focus on:
- Consistency with node patterns (INPUT_TYPES, RETURN_TYPES, FUNCTION, CATEGORY)
- No breaking changes to existing node interfaces
Files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
🧠 Learnings (7)
📚 Learning: 2026-02-21T14:01:41.482Z
Learnt from: pythongosssss
Repo: Comfy-Org/ComfyUI PR: 12555
File: comfy_extras/nodes_glsl.py:719-724
Timestamp: 2026-02-21T14:01:41.482Z
Learning: In PyOpenGL, bare Python scalars can be accepted for 1-element array parameters by NumberHandler. This means you can pass an int/float directly to OpenGL texture deletion (e.g., glDeleteTextures(tex)) without wrapping in a list. Verify function-specific expectations and ensure types match what the OpenGL call expects; use explicit lists only when the API requires an array.
Applied to files:
tests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pynodes.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pycomfy/model_detection.pytests-unit/comfy_test/paint_parity/harness.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/loader.pytests-unit/comfy_test/paint_parity/capture_reference.pycomfy/latent_formats.pytests-unit/comfy_test/paint_parity/bundle_format.pycomfy_extras/nodes_save_3d.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/ldm/hunyuan3d/paint/attention.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/unet.pytests-unit/comfy_test/test_hunyuan3d_paint.py
📚 Learning: 2026-05-13T12:31:45.069Z
Learnt from: rattus128
Repo: Comfy-Org/ComfyUI PR: 13802
File: comfy/pinned_memory.py:19-30
Timestamp: 2026-05-13T12:31:45.069Z
Learning: When reviewing code that uses comfy/pinned_memory.py’s `HostBuffer.extend(size=..., reallocate=...)`: by default (`reallocate` is not True / False), `extend(size=...)` is a *relative increment* that grows the buffer by `size` bytes—so slicing like `[offset:offset+size]` after `hostbuf.extend(size=size)` is correct and the argument should not be rewritten to `offset + size`. Only in the single-segment reallocation mode (`reallocate=True`, e.g., as used by `resize_pin_buffer()` in `comfy/model_management.py`) should `size` be treated as an *absolute target* and the call/arguments should be checked accordingly.
Applied to files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pycomfy/model_detection.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/unet.py
📚 Learning: 2026-05-04T18:30:37.579Z
Learnt from: Talmaj
Repo: Comfy-Org/ComfyUI PR: 13655
File: comfy/model_detection.py:907-917
Timestamp: 2026-05-04T18:30:37.579Z
Learning: In ComfyUI’s internal supported model implementations (comfy/supported_models_base.py and comfy/supported_models/*.py), ensure model classes do not override matches() in their own class bodies. All supported models should use BASE.matches() for backward compatibility; if a future change introduces a matches() override in a subclass, treat it as a backward-compatibility risk and require additional review/testing to confirm behavior remains consistent with BASE.matches().
Applied to files:
comfy/supported_models.py
📚 Learning: 2026-03-04T14:05:31.426Z
Learnt from: jtydhr88
Repo: Comfy-Org/ComfyUI PR: 12757
File: comfy_extras/nodes_custom_sampler.py:1069-1089
Timestamp: 2026-03-04T14:05:31.426Z
Learning: In the ComfyUI sampling pipeline, treat percent_to_sigma(0.0) as a sentinel value (999999999.9) that means starting from pure noise. This is consistent with BasicScheduler via calculate_sigmas. The SamplingPercentToSigma node’s return_actual_sigma flag differentiates this sentinel from sigma_max. Reviewers should not flag CurveToSigmas or similar nodes that rely on percent_to_sigma as bugs; downstream samplers are expected to handle the sentinel correctly. When reviewing related sampling-related code, assume this sentinel semantics unless there is explicit handling for a real sigma_max.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
📚 Learning: 2026-04-04T13:29:15.653Z
Learnt from: kijai
Repo: Comfy-Org/ComfyUI PR: 13258
File: comfy_extras/nodes_frame_interpolation.py:151-189
Timestamp: 2026-04-04T13:29:15.653Z
Learning: In this ComfyUI codebase, node `execute()` inference is already run under a global `torch.inference_mode()` context established in the execution engine (e.g., `execution.py` around line ~732). During review, avoid recommending changes that wrap node inference loops in `torch.inference_mode()`—it is already applied, so such suggestions are likely redundant.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
📚 Learning: 2026-05-09T18:40:40.199Z
Learnt from: kijai
Repo: Comfy-Org/ComfyUI PR: 13813
File: comfy_extras/nodes_wandancer.py:868-872
Timestamp: 2026-05-09T18:40:40.199Z
Learning: When building video/temporal decoding nodes that call ComfyUI’s VAE.decode (comfy/sd.py), leverage VAE.decode’s existing VRAM-aware chunking along dim 0. Reshape or transpose the latent so the temporal dimension T is folded into dim 0 (e.g., transform a latent of shape [B, T, C, H, W] into [B*T, C, H, W] before calling vae.decode). This lets VAE.decode do chunked decoding without needing an explicit per-frame loop inside the node itself.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
📚 Learning: 2026-05-20T00:10:14.673Z
Learnt from: Pauan
Repo: Comfy-Org/ComfyUI PR: 13997
File: comfy_extras/nodes_string.py:12-25
Timestamp: 2026-05-20T00:10:14.673Z
Learning: In the ComfyUI `comfy_extras/` codebase, some nodes intentionally ship with a default input string that references parameters that may not yet be connected. If the default would raise a `KeyError` (e.g., examples like `MathExpression` default `a + b`, or `StringFormat` default `{a}` with `min=0` and autogrow inputs), treat it as an intentional “hint default” UX pattern, not a bug. During review, do not flag this behavior or recommend changing `min` to `1` or altering the default to an empty string solely to avoid the `KeyError`.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
🪛 ast-grep (0.44.1)
tests-unit/comfy_test/paint_parity/compare_reference.py
[warning] 63-63: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(args.out, "w", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
tests-unit/comfy_test/paint_parity/capture_reference.py
[warning] 66-66: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "r", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
[warning] 92-92: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(os.path.join(args.unet_dir, "config.json"), "r", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
tests-unit/comfy_test/paint_parity/bundle_format.py
[info] 67-67: use jsonify instead of json.dumps for JSON output
Context: json.dumps(v)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
tests-unit/comfy_test/test_hunyuan3d_paint_render.py
[warning] 382-382: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "rb")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
[warning] 530-530: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "rb")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
[warning] 619-619: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "rb")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
🔇 Additional comments (31)
tests-unit/comfy_test/paint_parity/README.md (1)
1-58: LGTM!tests-unit/comfy_test/paint_parity/compare_reference.py (1)
1-71: LGTM!tests-unit/comfy_test/paint_parity/make_goldens.py (1)
1-33: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint_parity.py (1)
1-67: LGTM!comfy/ldm/hunyuan3d/paint/attention.py (1)
59-258: LGTM!comfy/ldm/hunyuan3d/paint/unet.py (1)
657-738: LGTM!comfy/latent_formats.py (1)
778-787: LGTM!comfy/ldm/hunyuan3d/paint/loader.py (1)
13-157: LGTM!comfy/model_base.py (1)
2065-2098: LGTM!comfy/model_detection.py (1)
727-731: LGTM!comfy/supported_models.py (1)
1556-1588: LGTM!Also applies to: 2447-2447
comfy/ldm/hunyuan3d/paint/__init__.py (1)
1-4: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint.py (4)
1-148: LGTM!
151-224: LGTM!
227-341: LGTM!
343-446: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint_render.py (3)
32-243: LGTM!
248-443: LGTM!
449-626: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint_conventions.py (2)
55-176: LGTM!
182-368: LGTM!comfy/ldm/hunyuan3d/paint/CONVENTIONS.md (1)
1-102: LGTM!comfy/ldm/hunyuan3d/paint/render.py (1)
183-303: LGTM!comfy_api/latest/_util/geometry_types.py (1)
37-50: LGTM!comfy_extras/nodes_hunyuan3d_paint.py (3)
50-97: LGTM!
165-294: LGTM!
333-365: LGTM!nodes.py (1)
2450-2450: LGTM!comfy_extras/nodes_save_3d.py (3)
79-169: LGTM!
269-289: LGTM!
413-433: LGTM!
|
Addressed the review in the latest push (also rebased onto current master):
81 tests pass post-rebase (paint suites + model detection), ruff clean. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@comfy/ldm/hunyuan3d/paint/CONVENTIONS.md`:
- Around line 18-22: The World frame description in normalize_mesh() incorrectly
identifies MESH_SCALE_FACTOR as the maximum vertex radius. Update it to describe
1.15 as the bounding-sphere diameter, or state the resulting maximum radius as
approximately 0.575, while preserving the existing transform and centering
details.
In `@tests-unit/comfy_test/test_hunyuan3d_paint_render.py`:
- Line 123: The test module keeps standard-library and third-party imports
inside test logic unnecessarily. Move math, BytesIO, numpy, and PIL.Image
imports to module scope, while retaining deferred comfy.* imports that depend on
args.cpu or established import-order requirements.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: ae4f2476-5c75-4210-8346-994e16e8d29d
📥 Commits
Reviewing files that changed from the base of the PR and between 3ed84cf and afc1074449ef3168729489205aaeeade4d3429fc.
📒 Files selected for processing (27)
comfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/CONVENTIONS.mdcomfy/ldm/hunyuan3d/paint/__init__.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/unet.pycomfy/model_base.pycomfy/model_detection.pycomfy/supported_models.pycomfy_api/latest/_util/geometry_types.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy_extras/nodes_save_3d.pynodes.pytests-unit/comfy_test/paint_parity/README.mdtests-unit/comfy_test/paint_parity/__init__.pytests-unit/comfy_test/paint_parity/bundle_format.pytests-unit/comfy_test/paint_parity/capture_reference.pytests-unit/comfy_test/paint_parity/compare_reference.pytests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensorstests-unit/comfy_test/paint_parity/harness.pytests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/parity_report.mdtests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/test_hunyuan3d_paint_render.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (7)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Keep changes small, direct, and limited to the narrowest code path and fewest files necessary; prefer practical fixes over broad architectural work.
Prefer fewer dependencies and do not add a ComfyUI dependency unless absolutely necessary.
Remove obsolete code, dead branches, unused options, debug prints, and unnecessary compatibility paths.
Preserve existing APIs, node names, model-loading behavior, file layout, and workflow compatibility unless replacement is explicit.
Keep architectural layers focused; do not leak UI, API, workflow, queue, persistence, telemetry, model-loading, node, or execution concerns into unrelated layers.
Shared core modules should depend only on lower-level primitives and their own domain concepts; higher-level concepts belong at callers, adapters, services, or boundaries.
Pass only the narrowest data needed across boundaries and keep identity mapping, persistence, history, telemetry, response shaping, and UI state in their owning layers.
Before touching many files, identify the smallest owner layer; use caller-side mappings, adapters, events, or narrow interfaces instead of exposing private concepts across layers.
Core ComfyUI code must not make unsolicited internet requests or add uploads, telemetry, analytics, tracking, reporting, update checks, remote configuration, licensing checks, or similar outbound paths.
Model downloading is allowed only when explicitly authorized by the user, limited to the requested artifact, and free of telemetry, tracking, unrelated metadata, or background activity.
Warning and info messages should be short and actionable; documentation and README changes should be concise, factual, and tied to changed behavior.
Use short direct commit subjects such asFix ...,Add ...,Support ...,Remove ..., orUpdate ...; keep PR descriptions short and state the problem, behavior change, and tests.
Prefer one coherent behavioral change per commit and prioritize crashes, incorrect dtype/device behavior, m...
Files:
tests-unit/comfy_test/parity_report.mdcomfy/ldm/hunyuan3d/paint/__init__.pytests-unit/comfy_test/paint_parity/README.mdnodes.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/paint_parity/make_goldens.pycomfy/model_detection.pycomfy/supported_models.pycomfy/ldm/hunyuan3d/paint/CONVENTIONS.mdtests-unit/comfy_test/paint_parity/capture_reference.pytests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensorscomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy_extras/nodes_save_3d.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/paint_parity/harness.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/model_base.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy/ldm/hunyuan3d/paint/attention.pytests-unit/comfy_test/paint_parity/bundle_format.pycomfy/ldm/hunyuan3d/paint/unet.py
**
⚙️ CodeRabbit configuration file
**: IMPORTANT: Only comment on issues directly introduced by this PR's code changes.
Treat AGENTS.md as mandatory repository policy, not optional style guidance.
Flag PR changes that violate AGENTS.md even when the code is otherwise functional.
In particular, enforce architecture boundaries, dtype/device/memory rules,
interface contracts, import style, no unnecessary try/except blocks, no inline
imports, no outbound internet paths in core ComfyUI, and narrow scoped fixes.
Prefer direct findings over suggestions when a rule is violated. Only ignore
AGENTS.md when it clearly conflicts with a newer explicit maintainer instruction
in the PR.
Do NOT flag pre-existing issues in code that was merely moved, re-indented,
de-indented, or reformatted without logic changes. If code appears in the diff
only due to whitespace or structural reformatting (e.g., removing awith:block),
treat it as unchanged. Contributors should not feel obligated to address
pre-existing issues outside the scope of their contribution.
Files:
tests-unit/comfy_test/parity_report.mdcomfy/ldm/hunyuan3d/paint/__init__.pytests-unit/comfy_test/paint_parity/README.mdnodes.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/paint_parity/make_goldens.pycomfy/model_detection.pycomfy/supported_models.pycomfy/ldm/hunyuan3d/paint/CONVENTIONS.mdtests-unit/comfy_test/paint_parity/capture_reference.pytests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensorscomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy_extras/nodes_save_3d.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/paint_parity/harness.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/model_base.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy/ldm/hunyuan3d/paint/attention.pytests-unit/comfy_test/paint_parity/bundle_format.pycomfy/ldm/hunyuan3d/paint/unet.py
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Keep state and capability flags on the object that owns the behavior; use explicit parent-owned fields rather than probing children withgetattrfor parent control flow.
Keep public methods aligned with caller contracts; preserve arguments, parameter order, return types, side effects, and error behavior unless all affected interfaces are intentionally updated.
Do not add unused compatibility parameters, flags, attributes, constructor options, or model-specific options to shared helpers.
Normalize third-party and upstream return conventions at integration boundaries so core code receives the expected type and shape.
Avoid caller-side unwrapping such asout = out[0]unless the called interface documents that return structure.
Do not addtorch.no_grad,torch.inference_mode, or inference-mode wrappers; only disable a globally enabled inference mode when a training path requires gradients.
Do not add freeze, unfreeze, or trainability toggles to ComfyUI model classes.
Remove training-only behavior such as dropout from inference models while preserving checkpoint and state-dict compatibility, usingnn.Identitywhen necessary to retain slots.
Keep imports at module scope; use inline imports only for established optional-backend probes or import-cycle avoidance.
Usetry/exceptonly for optional dependency, platform, or backend detection with a useful fallback, and prefer specific exception types.
Do not add code for unsupported pinned library versions or obsolete PyTorch workarounds; unsupported formats, quantization metadata, and bad states should fail clearly.
Match local file style and keep comments sparse, useful, and non-obvious; remove comments that merely restate code.
Files:
comfy/ldm/hunyuan3d/paint/__init__.pynodes.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/paint_parity/make_goldens.pycomfy/model_detection.pycomfy/supported_models.pytests-unit/comfy_test/paint_parity/capture_reference.pycomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy_extras/nodes_save_3d.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/paint_parity/harness.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/model_base.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy/ldm/hunyuan3d/paint/attention.pytests-unit/comfy_test/paint_parity/bundle_format.pycomfy/ldm/hunyuan3d/paint/unet.py
comfy/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
comfy/**/*.py: Treat dtype, device placement, VRAM use, offloading, and memory behavior as correctness concerns; use existing ComfyUI quantization, memory, offload, and optimized-operation helpers.
Prefer shared optimized kernels, backend dispatchers, and documented interfaces over duplicate handwritten operations; treat selected backend callables as opaque.
Do not duplicate operations with custom float32-upcasting inference kernels; use generic ComfyUI operations or native PyTorch operations.
If a model constructor has anoperationsparameter, assume it is neverNone; do not add fallback torch operations.
Avoid unnecessary parameters in model, block, and operation constructors or forwards; reuse existing model classes, blocks, operations, and helpers.
Model detectors must inspect only the first dimension of linear weights, guard every dereferenced state-dict key, and order specific signatures before broad fallbacks.
Avoideinopsin core inference code; use native tensor operations such asreshape,view,permute,transpose,flatten, and related methods.
Keep metadata, counters, shape calculations, indices, split boundaries, and control-flow values as Python values rather than tensors.
Avoid unnecessary casts and transfers; preserve intended compute and storage dtypes, tensor shapes, and backend result contracts.
Keep model-native latent layout handling inside the model or latent-format owner rather than reshaping it in nodes or caller-side adapters.
DiT models must pad every patchified target or reference input withcomfy.ldm.common_dit.pad_to_patch_sizeand crop only the target output back to its original dimensions.
Do not add defensive shape, configuration, or dtype casts that merely obscure a clear tensor-operation failure; validate only at meaningful boundaries.
Raw parameters not owned by an operation should be cast at use withcomfy.ops.cast_to_inputorcomfy.model_management.cast_to; model constructors should not contain dtype workaro...
Files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy/model_detection.pycomfy/supported_models.pycomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/unet.py
comfy/**
⚙️ CodeRabbit configuration file
comfy/**: Core ML/diffusion engine. Focus on:
- Backward compatibility (breaking changes affect all custom nodes)
- Memory management and GPU resource handling
- Performance implications in hot paths
- Thread safety for concurrent execution
Files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy/model_detection.pycomfy/supported_models.pycomfy/ldm/hunyuan3d/paint/CONVENTIONS.mdcomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/unet.py
nodes.py
⚙️ CodeRabbit configuration file
nodes.py: Core node definitions (2500+ lines). Focus on:
- Backward compatibility of NODE_CLASS_MAPPINGS
- Consistency of INPUT_TYPES return format
Files:
nodes.py
comfy_extras/**
⚙️ CodeRabbit configuration file
comfy_extras/**: Community-contributed extra nodes. Focus on:
- Consistency with node patterns (INPUT_TYPES, RETURN_TYPES, FUNCTION, CATEGORY)
- No breaking changes to existing node interfaces
Files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
🧠 Learnings (7)
📚 Learning: 2026-02-21T14:01:41.482Z
Learnt from: pythongosssss
Repo: Comfy-Org/ComfyUI PR: 12555
File: comfy_extras/nodes_glsl.py:719-724
Timestamp: 2026-02-21T14:01:41.482Z
Learning: In PyOpenGL, bare Python scalars can be accepted for 1-element array parameters by NumberHandler. This means you can pass an int/float directly to OpenGL texture deletion (e.g., glDeleteTextures(tex)) without wrapping in a list. Verify function-specific expectations and ensure types match what the OpenGL call expects; use explicit lists only when the API requires an array.
Applied to files:
comfy/ldm/hunyuan3d/paint/__init__.pynodes.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/paint_parity/make_goldens.pycomfy/model_detection.pycomfy/supported_models.pytests-unit/comfy_test/paint_parity/capture_reference.pycomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy_extras/nodes_save_3d.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/paint_parity/harness.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/model_base.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy/ldm/hunyuan3d/paint/attention.pytests-unit/comfy_test/paint_parity/bundle_format.pycomfy/ldm/hunyuan3d/paint/unet.py
📚 Learning: 2026-05-13T12:31:45.069Z
Learnt from: rattus128
Repo: Comfy-Org/ComfyUI PR: 13802
File: comfy/pinned_memory.py:19-30
Timestamp: 2026-05-13T12:31:45.069Z
Learning: When reviewing code that uses comfy/pinned_memory.py’s `HostBuffer.extend(size=..., reallocate=...)`: by default (`reallocate` is not True / False), `extend(size=...)` is a *relative increment* that grows the buffer by `size` bytes—so slicing like `[offset:offset+size]` after `hostbuf.extend(size=size)` is correct and the argument should not be rewritten to `offset + size`. Only in the single-segment reallocation mode (`reallocate=True`, e.g., as used by `resize_pin_buffer()` in `comfy/model_management.py`) should `size` be treated as an *absolute target* and the call/arguments should be checked accordingly.
Applied to files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy/model_detection.pycomfy/supported_models.pycomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/model_base.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/unet.py
📚 Learning: 2026-05-04T18:30:37.579Z
Learnt from: Talmaj
Repo: Comfy-Org/ComfyUI PR: 13655
File: comfy/model_detection.py:907-917
Timestamp: 2026-05-04T18:30:37.579Z
Learning: In ComfyUI’s internal supported model implementations (comfy/supported_models_base.py and comfy/supported_models/*.py), ensure model classes do not override matches() in their own class bodies. All supported models should use BASE.matches() for backward compatibility; if a future change introduces a matches() override in a subclass, treat it as a backward-compatibility risk and require additional review/testing to confirm behavior remains consistent with BASE.matches().
Applied to files:
comfy/supported_models.py
📚 Learning: 2026-03-04T14:05:31.426Z
Learnt from: jtydhr88
Repo: Comfy-Org/ComfyUI PR: 12757
File: comfy_extras/nodes_custom_sampler.py:1069-1089
Timestamp: 2026-03-04T14:05:31.426Z
Learning: In the ComfyUI sampling pipeline, treat percent_to_sigma(0.0) as a sentinel value (999999999.9) that means starting from pure noise. This is consistent with BasicScheduler via calculate_sigmas. The SamplingPercentToSigma node’s return_actual_sigma flag differentiates this sentinel from sigma_max. Reviewers should not flag CurveToSigmas or similar nodes that rely on percent_to_sigma as bugs; downstream samplers are expected to handle the sentinel correctly. When reviewing related sampling-related code, assume this sentinel semantics unless there is explicit handling for a real sigma_max.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
📚 Learning: 2026-04-04T13:29:15.653Z
Learnt from: kijai
Repo: Comfy-Org/ComfyUI PR: 13258
File: comfy_extras/nodes_frame_interpolation.py:151-189
Timestamp: 2026-04-04T13:29:15.653Z
Learning: In this ComfyUI codebase, node `execute()` inference is already run under a global `torch.inference_mode()` context established in the execution engine (e.g., `execution.py` around line ~732). During review, avoid recommending changes that wrap node inference loops in `torch.inference_mode()`—it is already applied, so such suggestions are likely redundant.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
📚 Learning: 2026-05-09T18:40:40.199Z
Learnt from: kijai
Repo: Comfy-Org/ComfyUI PR: 13813
File: comfy_extras/nodes_wandancer.py:868-872
Timestamp: 2026-05-09T18:40:40.199Z
Learning: When building video/temporal decoding nodes that call ComfyUI’s VAE.decode (comfy/sd.py), leverage VAE.decode’s existing VRAM-aware chunking along dim 0. Reshape or transpose the latent so the temporal dimension T is folded into dim 0 (e.g., transform a latent of shape [B, T, C, H, W] into [B*T, C, H, W] before calling vae.decode). This lets VAE.decode do chunked decoding without needing an explicit per-frame loop inside the node itself.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
📚 Learning: 2026-05-20T00:10:14.673Z
Learnt from: Pauan
Repo: Comfy-Org/ComfyUI PR: 13997
File: comfy_extras/nodes_string.py:12-25
Timestamp: 2026-05-20T00:10:14.673Z
Learning: In the ComfyUI `comfy_extras/` codebase, some nodes intentionally ship with a default input string that references parameters that may not yet be connected. If the default would raise a `KeyError` (e.g., examples like `MathExpression` default `a + b`, or `StringFormat` default `{a}` with `min=0` and autogrow inputs), treat it as an intentional “hint default” UX pattern, not a bug. During review, do not flag this behavior or recommend changing `min` to `1` or altering the default to an empty string solely to avoid the `KeyError`.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
🪛 ast-grep (0.44.1)
tests-unit/comfy_test/paint_parity/compare_reference.py
[warning] 64-64: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(args.out, "w", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
tests-unit/comfy_test/paint_parity/capture_reference.py
[warning] 66-66: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "r", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
[warning] 94-94: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(os.path.join(args.unet_dir, "config.json"), "r", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
tests-unit/comfy_test/test_hunyuan3d_paint_render.py
[warning] 382-382: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "rb")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
[warning] 530-530: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "rb")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
[warning] 619-619: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "rb")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
tests-unit/comfy_test/paint_parity/bundle_format.py
[info] 67-67: use jsonify instead of json.dumps for JSON output
Context: json.dumps(v)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🔇 Additional comments (40)
tests-unit/comfy_test/paint_parity/capture_reference.py (1)
147-158: 📐 Maintainability & Code Quality | ⚡ Quick winRemove the leftover
torch.inference_mode()wrapper here too.This exact site was already flagged for removal in a prior review round (paired with the
harness.pyfixes at lines 44-48/92-101, which now let the caller own the execution context). Those sibling fixes landed, but this wrapper around the reference model's forward call was left in place.🔧 Proposed fix
- with torch.inference_mode(): - out = model( - tensors["input/sample"], - tensors["input/timestep"], - tensors["input/encoder_hidden_states"], - ref_latents=tensors["input/ref_latents"], - embeds_normal=tensors["input/embeds_normal"], - embeds_position=tensors["input/embeds_position"], - position_maps=tensors["input/position_maps"], - dino_hidden_states=tensors["input/dino_hidden_states"], - mva_scale=1.0, ref_scale=1.0, cache={}, - ) + out = model( + tensors["input/sample"], + tensors["input/timestep"], + tensors["input/encoder_hidden_states"], + ref_latents=tensors["input/ref_latents"], + embeds_normal=tensors["input/embeds_normal"], + embeds_position=tensors["input/embeds_position"], + position_maps=tensors["input/position_maps"], + dino_hidden_states=tensors["input/dino_hidden_states"], + mva_scale=1.0, ref_scale=1.0, cache={}, + )As per coding guidelines, "Do not add
torch.no_grad,torch.inference_mode, or inference-mode wrappers; only disable a globally enabled inference mode when a training path requires gradients."Source: Coding guidelines
tests-unit/comfy_test/paint_parity/README.md (1)
1-58: LGTM!tests-unit/comfy_test/paint_parity/bundle_format.py (1)
1-117: LGTM!tests-unit/comfy_test/paint_parity/compare_reference.py (1)
1-73: LGTM!tests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensors (1)
1-218: LGTM!tests-unit/comfy_test/paint_parity/harness.py (1)
37-125: LGTM!tests-unit/comfy_test/paint_parity/make_goldens.py (1)
1-34: LGTM!tests-unit/comfy_test/parity_report.md (1)
1-18: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint_parity.py (1)
1-68: LGTM!comfy/ldm/hunyuan3d/paint/render.py (3)
119-131: LGTM!
495-499: LGTM!
188-308: LGTM!Also applies to: 433-534
comfy_extras/nodes_hunyuan3d_paint.py (1)
78-97: LGTM!Also applies to: 165-294, 333-365
nodes.py (1)
2450-2450: LGTM!comfy_api/latest/_util/geometry_types.py (1)
37-37: LGTM!Also applies to: 48-50
comfy_extras/nodes_save_3d.py (1)
79-94: LGTM!Also applies to: 129-160, 169-169, 260-290, 413-433
comfy/ldm/hunyuan3d/paint/attention.py (1)
20-311: LGTM!comfy/ldm/hunyuan3d/paint/unet.py (1)
22-741: LGTM!comfy/latent_formats.py (1)
778-787: LGTM!comfy/ldm/hunyuan3d/paint/loader.py (1)
1-157: LGTM!comfy/model_base.py (1)
50-50: LGTM!Also applies to: 2065-2098
comfy/model_detection.py (1)
2-2: LGTM!Also applies to: 727-731
comfy/supported_models.py (1)
1556-1587: LGTM!Also applies to: 2447-2447
comfy/ldm/hunyuan3d/paint/__init__.py (1)
1-4: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint_render.py (6)
32-78: LGTM!
90-132: LGTM!
156-242: LGTM!
248-376: LGTM!
403-443: LGTM!
454-626: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint.py (9)
1-42: LGTM!
44-52: 📐 Maintainability & Code Quality | ⚡ Quick winNon-deterministic seed offset via
hash().
hash(name)on astris randomized per-process (PYTHONHASHSEED), so the per-parameter seed offset — and therefore the actual init values used by every test calling_init_weights— differs across separate pytest invocations even thoughseedis fixed. This undermines the reproducibility this helper is meant to provide (e.g. reproducing a numeric failure locally). Use a stable hash (e.g.zlib.crc32(name.encode())) instead of the built-inhash().🔧 Proposed fix
+import zlib + def _init_weights(model, seed=0, scale=0.03): """Small seeded init: disable_weight_init leaves parameters uninitialized (torch.empty garbage), which is fine for shape tests but overflows through a deep net; tests asserting finite numerics need real (small) weights.""" with torch.no_grad(): for name, p in sorted(model.named_parameters()): - g = torch.Generator().manual_seed(seed + (hash(name) % 65536)) + g = torch.Generator().manual_seed(seed + (zlib.crc32(name.encode()) % 65536)) p.copy_(torch.randn(p.shape, generator=g, dtype=torch.float32).to(p.dtype) * scale) return model
55-83: LGTM!
85-148: LGTM!
151-225: LGTM!
227-298: LGTM!
300-341: LGTM!
343-375: LGTM!
377-446: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint_conventions.py (1)
1-369: LGTM!
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests-unit/comfy_test/test_hunyuan3d_paint_render.py (1)
492-497: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winKeep the coverage check from becoming vacuous.
If baking produces no covered texels, all
torch.allcloseassertions pass on empty tensors, so this test can miss a broken bake entirely. Assert thatcoveredcontains at least one texel before validating MR channels.Proposed fix
covered = alb_tex[0].abs().sum(-1) > 0 + assert bool(covered.any()), "expected baked texture coverage" assert torch.allclose(mr_tex[0][covered][:, 0], torch.full((int(covered.sum()),), 0.2), atol=1e-3)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests-unit/comfy_test/test_hunyuan3d_paint_render.py` around lines 492 - 497, Update the coverage validation in the test around the covered mask to assert that covered contains at least one texel before running the MR channel comparisons. Keep the existing torch.allclose checks and expected channel values unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@tests-unit/comfy_test/test_hunyuan3d_paint_render.py`:
- Around line 492-497: Update the coverage validation in the test around the
covered mask to assert that covered contains at least one texel before running
the MR channel comparisons. Keep the existing torch.allclose checks and expected
channel values unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 9210662f-abe9-43ec-b237-21ae8696f55f
📥 Commits
Reviewing files that changed from the base of the PR and between afc1074449ef3168729489205aaeeade4d3429fc and 630bb7c2d77ed7fad057e25f01aa223df0e50131.
📒 Files selected for processing (2)
comfy/ldm/hunyuan3d/paint/CONVENTIONS.mdtests-unit/comfy_test/test_hunyuan3d_paint_render.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Keep changes small, direct, and limited to the narrowest code path and fewest files necessary; prefer practical fixes over broad architectural work.
Prefer fewer dependencies and do not add a ComfyUI dependency unless absolutely necessary.
Remove obsolete code, dead branches, unused options, debug prints, and unnecessary compatibility paths.
Preserve existing APIs, node names, model-loading behavior, file layout, and workflow compatibility unless replacement is explicit.
Keep architectural layers focused; do not leak UI, API, workflow, queue, persistence, telemetry, model-loading, node, or execution concerns into unrelated layers.
Shared core modules should depend only on lower-level primitives and their own domain concepts; higher-level concepts belong at callers, adapters, services, or boundaries.
Pass only the narrowest data needed across boundaries and keep identity mapping, persistence, history, telemetry, response shaping, and UI state in their owning layers.
Before touching many files, identify the smallest owner layer; use caller-side mappings, adapters, events, or narrow interfaces instead of exposing private concepts across layers.
Core ComfyUI code must not make unsolicited internet requests or add uploads, telemetry, analytics, tracking, reporting, update checks, remote configuration, licensing checks, or similar outbound paths.
Model downloading is allowed only when explicitly authorized by the user, limited to the requested artifact, and free of telemetry, tracking, unrelated metadata, or background activity.
Warning and info messages should be short and actionable; documentation and README changes should be concise, factual, and tied to changed behavior.
Use short direct commit subjects such asFix ...,Add ...,Support ...,Remove ..., orUpdate ...; keep PR descriptions short and state the problem, behavior change, and tests.
Prefer one coherent behavioral change per commit and prioritize crashes, incorrect dtype/device behavior, m...
Files:
comfy/ldm/hunyuan3d/paint/CONVENTIONS.mdtests-unit/comfy_test/test_hunyuan3d_paint_render.py
**
⚙️ CodeRabbit configuration file
**: IMPORTANT: Only comment on issues directly introduced by this PR's code changes.
Treat AGENTS.md as mandatory repository policy, not optional style guidance.
Flag PR changes that violate AGENTS.md even when the code is otherwise functional.
In particular, enforce architecture boundaries, dtype/device/memory rules,
interface contracts, import style, no unnecessary try/except blocks, no inline
imports, no outbound internet paths in core ComfyUI, and narrow scoped fixes.
Prefer direct findings over suggestions when a rule is violated. Only ignore
AGENTS.md when it clearly conflicts with a newer explicit maintainer instruction
in the PR.
Do NOT flag pre-existing issues in code that was merely moved, re-indented,
de-indented, or reformatted without logic changes. If code appears in the diff
only due to whitespace or structural reformatting (e.g., removing awith:block),
treat it as unchanged. Contributors should not feel obligated to address
pre-existing issues outside the scope of their contribution.
Files:
comfy/ldm/hunyuan3d/paint/CONVENTIONS.mdtests-unit/comfy_test/test_hunyuan3d_paint_render.py
comfy/**
⚙️ CodeRabbit configuration file
comfy/**: Core ML/diffusion engine. Focus on:
- Backward compatibility (breaking changes affect all custom nodes)
- Memory management and GPU resource handling
- Performance implications in hot paths
- Thread safety for concurrent execution
Files:
comfy/ldm/hunyuan3d/paint/CONVENTIONS.md
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Keep state and capability flags on the object that owns the behavior; use explicit parent-owned fields rather than probing children withgetattrfor parent control flow.
Keep public methods aligned with caller contracts; preserve arguments, parameter order, return types, side effects, and error behavior unless all affected interfaces are intentionally updated.
Do not add unused compatibility parameters, flags, attributes, constructor options, or model-specific options to shared helpers.
Normalize third-party and upstream return conventions at integration boundaries so core code receives the expected type and shape.
Avoid caller-side unwrapping such asout = out[0]unless the called interface documents that return structure.
Do not addtorch.no_grad,torch.inference_mode, or inference-mode wrappers; only disable a globally enabled inference mode when a training path requires gradients.
Do not add freeze, unfreeze, or trainability toggles to ComfyUI model classes.
Remove training-only behavior such as dropout from inference models while preserving checkpoint and state-dict compatibility, usingnn.Identitywhen necessary to retain slots.
Keep imports at module scope; use inline imports only for established optional-backend probes or import-cycle avoidance.
Usetry/exceptonly for optional dependency, platform, or backend detection with a useful fallback, and prefer specific exception types.
Do not add code for unsupported pinned library versions or obsolete PyTorch workarounds; unsupported formats, quantization metadata, and bad states should fail clearly.
Match local file style and keep comments sparse, useful, and non-obvious; remove comments that merely restate code.
Files:
tests-unit/comfy_test/test_hunyuan3d_paint_render.py
🧠 Learnings (1)
📚 Learning: 2026-02-21T14:01:41.482Z
Learnt from: pythongosssss
Repo: Comfy-Org/ComfyUI PR: 12555
File: comfy_extras/nodes_glsl.py:719-724
Timestamp: 2026-02-21T14:01:41.482Z
Learning: In PyOpenGL, bare Python scalars can be accepted for 1-element array parameters by NumberHandler. This means you can pass an int/float directly to OpenGL texture deletion (e.g., glDeleteTextures(tex)) without wrapping in a list. Verify function-specific expectations and ensure types match what the OpenGL call expects; use explicit lists only when the API requires an array.
Applied to files:
tests-unit/comfy_test/test_hunyuan3d_paint_render.py
🔇 Additional comments (2)
tests-unit/comfy_test/test_hunyuan3d_paint_render.py (1)
16-23: LGTM!Also applies to: 448-491, 498-540
comfy/ldm/hunyuan3d/paint/CONVENTIONS.md (1)
1-103: LGTM!
There was a problem hiding this comment.
Actionable comments posted: 11
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@comfy_api/latest/_util/geometry_types.py`:
- Line 37: Move the optional texture_mr parameter to the end of the MESH
constructor signature, after all existing positional parameters such as
vertex_counts, face_counts, and unlit. Preserve the current ordering of every
pre-existing parameter so positional callers retain their established bindings,
while keeping texture_mr optional.
In `@comfy_extras/nodes_hunyuan3d_paint.py`:
- Around line 92-93: Replace the early return in the validation branch around
cond with an explicit failure when the latent is not 5D or its view dimension is
not divisible by len(azims). Preserve normal processing for valid packed
latents, but ensure this misconfiguration cannot silently fall back to scalar
CFG.
- Around line 348-351: Update the adjacent albedo and MR bake calls in the paint
rendering flow to combine their view data into one six-channel input and invoke
paint_render.bake_multiview once with the shared geometry, UVs, cameras,
texture_size, and bake_exp. Split the returned channels and corresponding masks
back into albedo_tex/mask_a and mr_tex/mask_mr while preserving channel ordering
and independent per-channel results.
In `@comfy_extras/nodes_save_3d.py`:
- Around line 274-285: Update the material export flow around the outer
texture_png_bytes/TEXCOORD_0 guard so a metallic-roughness texture without a
base-color texture is not encoded into the BIN without references. Either emit
valid MR-only material references outside that guard or skip MR texture encoding
and buffer-byte accounting when the base texture is absent.
In `@comfy/ldm/hunyuan3d/paint/render.py`:
- Around line 248-259: The sampling loop in the area/sel chunk path allows a
single face to allocate its entire bounding-box area despite the chunk budget.
Update the logic around the per-face expansion using area, local, off, and pixel
coordinates to split oversized faces into bounded scanline bands or otherwise
cap each expansion by chunk_area; preserve the resulting global face indices and
pixel coordinates while ensuring temporary tensors never scale beyond the
configured chunk budget.
- Around line 244-247: Update the chunking loop in the rendering function
containing chunk_id to exploit its monotonic contiguous ranges: compute chunk
boundaries once, then derive each chunk’s face selection by slicing the
corresponding range instead of calling torch.nonzero(chunk_id == c) for every
chunk. Preserve empty-chunk handling and the existing per-chunk processing
behavior.
In `@comfy/ldm/hunyuan3d/paint/unet.py`:
- Around line 623-628: Replace zero-initialization with uninitialized allocation
for the checkpoint-owned parameters created in the pbr_setting loop and
learned_text_clip_ref, using torch.empty with the same shape, dtype, and device.
Preserve parameter registration and rely on the checkpoint loader to populate
every value.
In `@comfy/model_base.py`:
- Around line 2095-2097: Update the ref_scale handling in the surrounding
conditioning setup to avoid constructing a fixed float32 tensor with
torch.FloatTensor; create the value without forcing a concrete dtype, or ensure
it is cast to the attention input dtype at the application site, preserving
fp16/bf16 compute in the UNet.
In `@tests-unit/comfy_test/paint_parity/capture_reference.py`:
- Around line 175-176: Update the cpu_patch description in the capture reference
metadata to remove the obsolete conditional and always use the active patch
description, since cpu_patch is now unconditional. Keep the existing “none”
fallback removed from this metadata entry.
In `@tests-unit/comfy_test/paint_parity/compare_reference.py`:
- Around line 32-36: Move the safetensors.torch load_file import from inside
_load_state_dict to module scope, then keep the existing .safetensors branch
behavior unchanged while continuing to use torch.load for other paths.
In `@tests-unit/comfy_test/test_hunyuan3d_paint.py`:
- Around line 44-52: Update _init_weights to derive each parameter’s generator
seed deterministically without using Python’s salted hash(name), such as by
using the sorted-parameter index or a stable hash of the parameter name.
Preserve distinct per-parameter seeds, the existing base seed and scale
behavior, and reproducible finite initialization for the numerical tests.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: d43a6e67-35ed-445e-9eb5-b9f8c4f8685b
📥 Commits
Reviewing files that changed from the base of the PR and between c7540cfcd52c650d7c3308ab4316926b5ab834a6 and 58519ad.
📒 Files selected for processing (27)
comfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/CONVENTIONS.mdcomfy/ldm/hunyuan3d/paint/__init__.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/unet.pycomfy/model_base.pycomfy/model_detection.pycomfy/supported_models.pycomfy_api/latest/_util/geometry_types.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy_extras/nodes_save_3d.pynodes.pytests-unit/comfy_test/paint_parity/README.mdtests-unit/comfy_test/paint_parity/__init__.pytests-unit/comfy_test/paint_parity/bundle_format.pytests-unit/comfy_test/paint_parity/capture_reference.pytests-unit/comfy_test/paint_parity/compare_reference.pytests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensorstests-unit/comfy_test/paint_parity/harness.pytests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/parity_report.mdtests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/test_hunyuan3d_paint_render.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (7)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Keep changes small, direct, and limited to the narrowest code path and fewest files necessary; prefer practical fixes over broad architectural work.
Prefer fewer dependencies and do not add a ComfyUI dependency unless absolutely necessary.
Remove obsolete code, dead branches, unused options, debug prints, and unnecessary compatibility paths.
Preserve existing APIs, node names, model-loading behavior, file layout, and workflow compatibility unless replacement is explicit.
Keep architectural layers focused; do not leak UI, API, workflow, queue, persistence, telemetry, model-loading, node, or execution concerns into unrelated layers.
Shared core modules should depend only on lower-level primitives and their own domain concepts; higher-level concepts belong at callers, adapters, services, or boundaries.
Pass only the narrowest data needed across boundaries and keep identity mapping, persistence, history, telemetry, response shaping, and UI state in their owning layers.
Before touching many files, identify the smallest owner layer; use caller-side mappings, adapters, events, or narrow interfaces instead of exposing private concepts across layers.
Core ComfyUI code must not make unsolicited internet requests or add uploads, telemetry, analytics, tracking, reporting, update checks, remote configuration, licensing checks, or similar outbound paths.
Model downloading is allowed only when explicitly authorized by the user, limited to the requested artifact, and free of telemetry, tracking, unrelated metadata, or background activity.
Warning and info messages should be short and actionable; documentation and README changes should be concise, factual, and tied to changed behavior.
Use short direct commit subjects such asFix ...,Add ...,Support ...,Remove ..., orUpdate ...; keep PR descriptions short and state the problem, behavior change, and tests.
Prefer one coherent behavioral change per commit and prioritize crashes, incorrect dtype/device behavior, m...
Files:
tests-unit/comfy_test/parity_report.mdcomfy/ldm/hunyuan3d/paint/__init__.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/paint_parity/README.mdnodes.pycomfy/supported_models.pytests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensorscomfy/model_base.pycomfy/model_detection.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy/ldm/hunyuan3d/paint/loader.pytests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/paint_parity/capture_reference.pycomfy/ldm/hunyuan3d/paint/CONVENTIONS.mdtests-unit/comfy_test/paint_parity/harness.pycomfy_extras/nodes_save_3d.pycomfy/latent_formats.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/paint_parity/bundle_format.pytests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/unet.py
**
⚙️ CodeRabbit configuration file
**: IMPORTANT: Only comment on issues directly introduced by this PR's code changes.
Treat AGENTS.md as mandatory repository policy, not optional style guidance.
Flag PR changes that violate AGENTS.md even when the code is otherwise functional.
In particular, enforce architecture boundaries, dtype/device/memory rules,
interface contracts, import style, no unnecessary try/except blocks, no inline
imports, no outbound internet paths in core ComfyUI, and narrow scoped fixes.
Prefer direct findings over suggestions when a rule is violated. Only ignore
AGENTS.md when it clearly conflicts with a newer explicit maintainer instruction
in the PR.
Do NOT flag pre-existing issues in code that was merely moved, re-indented,
de-indented, or reformatted without logic changes. If code appears in the diff
only due to whitespace or structural reformatting (e.g., removing awith:block),
treat it as unchanged. Contributors should not feel obligated to address
pre-existing issues outside the scope of their contribution.
Files:
tests-unit/comfy_test/parity_report.mdcomfy/ldm/hunyuan3d/paint/__init__.pycomfy_api/latest/_util/geometry_types.pytests-unit/comfy_test/paint_parity/README.mdnodes.pycomfy/supported_models.pytests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensorscomfy/model_base.pycomfy/model_detection.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy/ldm/hunyuan3d/paint/loader.pytests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/paint_parity/capture_reference.pycomfy/ldm/hunyuan3d/paint/CONVENTIONS.mdtests-unit/comfy_test/paint_parity/harness.pycomfy_extras/nodes_save_3d.pycomfy/latent_formats.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/paint_parity/bundle_format.pytests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/unet.py
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Keep state and capability flags on the object that owns the behavior; use explicit parent-owned fields rather than probing children withgetattrfor parent control flow.
Keep public methods aligned with caller contracts; preserve arguments, parameter order, return types, side effects, and error behavior unless all affected interfaces are intentionally updated.
Do not add unused compatibility parameters, flags, attributes, constructor options, or model-specific options to shared helpers.
Normalize third-party and upstream return conventions at integration boundaries so core code receives the expected type and shape.
Avoid caller-side unwrapping such asout = out[0]unless the called interface documents that return structure.
Do not addtorch.no_grad,torch.inference_mode, or inference-mode wrappers; only disable a globally enabled inference mode when a training path requires gradients.
Do not add freeze, unfreeze, or trainability toggles to ComfyUI model classes.
Remove training-only behavior such as dropout from inference models while preserving checkpoint and state-dict compatibility, usingnn.Identitywhen necessary to retain slots.
Keep imports at module scope; use inline imports only for established optional-backend probes or import-cycle avoidance.
Usetry/exceptonly for optional dependency, platform, or backend detection with a useful fallback, and prefer specific exception types.
Do not add code for unsupported pinned library versions or obsolete PyTorch workarounds; unsupported formats, quantization metadata, and bad states should fail clearly.
Match local file style and keep comments sparse, useful, and non-obvious; remove comments that merely restate code.
Files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy_api/latest/_util/geometry_types.pynodes.pycomfy/supported_models.pycomfy/model_base.pycomfy/model_detection.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy/ldm/hunyuan3d/paint/loader.pytests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/paint_parity/capture_reference.pytests-unit/comfy_test/paint_parity/harness.pycomfy_extras/nodes_save_3d.pycomfy/latent_formats.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/paint_parity/bundle_format.pytests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/unet.py
comfy/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
comfy/**/*.py: Treat dtype, device placement, VRAM use, offloading, and memory behavior as correctness concerns; use existing ComfyUI quantization, memory, offload, and optimized-operation helpers.
Prefer shared optimized kernels, backend dispatchers, and documented interfaces over duplicate handwritten operations; treat selected backend callables as opaque.
Do not duplicate operations with custom float32-upcasting inference kernels; use generic ComfyUI operations or native PyTorch operations.
If a model constructor has anoperationsparameter, assume it is neverNone; do not add fallback torch operations.
Avoid unnecessary parameters in model, block, and operation constructors or forwards; reuse existing model classes, blocks, operations, and helpers.
Model detectors must inspect only the first dimension of linear weights, guard every dereferenced state-dict key, and order specific signatures before broad fallbacks.
Avoideinopsin core inference code; use native tensor operations such asreshape,view,permute,transpose,flatten, and related methods.
Keep metadata, counters, shape calculations, indices, split boundaries, and control-flow values as Python values rather than tensors.
Avoid unnecessary casts and transfers; preserve intended compute and storage dtypes, tensor shapes, and backend result contracts.
Keep model-native latent layout handling inside the model or latent-format owner rather than reshaping it in nodes or caller-side adapters.
DiT models must pad every patchified target or reference input withcomfy.ldm.common_dit.pad_to_patch_sizeand crop only the target output back to its original dimensions.
Do not add defensive shape, configuration, or dtype casts that merely obscure a clear tensor-operation failure; validate only at meaningful boundaries.
Raw parameters not owned by an operation should be cast at use withcomfy.ops.cast_to_inputorcomfy.model_management.cast_to; model constructors should not contain dtype workaro...
Files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pycomfy/model_base.pycomfy/model_detection.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/unet.py
comfy/**
⚙️ CodeRabbit configuration file
comfy/**: Core ML/diffusion engine. Focus on:
- Backward compatibility (breaking changes affect all custom nodes)
- Memory management and GPU resource handling
- Performance implications in hot paths
- Thread safety for concurrent execution
Files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pycomfy/model_base.pycomfy/model_detection.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/ldm/hunyuan3d/paint/CONVENTIONS.mdcomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/unet.py
nodes.py
⚙️ CodeRabbit configuration file
nodes.py: Core node definitions (2500+ lines). Focus on:
- Backward compatibility of NODE_CLASS_MAPPINGS
- Consistency of INPUT_TYPES return format
Files:
nodes.py
comfy_extras/**
⚙️ CodeRabbit configuration file
comfy_extras/**: Community-contributed extra nodes. Focus on:
- Consistency with node patterns (INPUT_TYPES, RETURN_TYPES, FUNCTION, CATEGORY)
- No breaking changes to existing node interfaces
Files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
🧠 Learnings (7)
📚 Learning: 2026-02-21T14:01:41.482Z
Learnt from: pythongosssss
Repo: Comfy-Org/ComfyUI PR: 12555
File: comfy_extras/nodes_glsl.py:719-724
Timestamp: 2026-02-21T14:01:41.482Z
Learning: In PyOpenGL, bare Python scalars can be accepted for 1-element array parameters by NumberHandler. This means you can pass an int/float directly to OpenGL texture deletion (e.g., glDeleteTextures(tex)) without wrapping in a list. Verify function-specific expectations and ensure types match what the OpenGL call expects; use explicit lists only when the API requires an array.
Applied to files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy_api/latest/_util/geometry_types.pynodes.pycomfy/supported_models.pycomfy/model_base.pycomfy/model_detection.pytests-unit/comfy_test/paint_parity/compare_reference.pycomfy/ldm/hunyuan3d/paint/loader.pytests-unit/comfy_test/paint_parity/make_goldens.pytests-unit/comfy_test/paint_parity/capture_reference.pytests-unit/comfy_test/paint_parity/harness.pycomfy_extras/nodes_save_3d.pycomfy/latent_formats.pytests-unit/comfy_test/test_hunyuan3d_paint_parity.pytests-unit/comfy_test/paint_parity/bundle_format.pytests-unit/comfy_test/test_hunyuan3d_paint.pytests-unit/comfy_test/test_hunyuan3d_paint_render.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/render.pytests-unit/comfy_test/test_hunyuan3d_paint_conventions.pycomfy_extras/nodes_hunyuan3d_paint.pycomfy/ldm/hunyuan3d/paint/unet.py
📚 Learning: 2026-05-13T12:31:45.069Z
Learnt from: rattus128
Repo: Comfy-Org/ComfyUI PR: 13802
File: comfy/pinned_memory.py:19-30
Timestamp: 2026-05-13T12:31:45.069Z
Learning: When reviewing code that uses comfy/pinned_memory.py’s `HostBuffer.extend(size=..., reallocate=...)`: by default (`reallocate` is not True / False), `extend(size=...)` is a *relative increment* that grows the buffer by `size` bytes—so slicing like `[offset:offset+size]` after `hostbuf.extend(size=size)` is correct and the argument should not be rewritten to `offset + size`. Only in the single-segment reallocation mode (`reallocate=True`, e.g., as used by `resize_pin_buffer()` in `comfy/model_management.py`) should `size` be treated as an *absolute target* and the call/arguments should be checked accordingly.
Applied to files:
comfy/ldm/hunyuan3d/paint/__init__.pycomfy/supported_models.pycomfy/model_base.pycomfy/model_detection.pycomfy/ldm/hunyuan3d/paint/loader.pycomfy/latent_formats.pycomfy/ldm/hunyuan3d/paint/attention.pycomfy/ldm/hunyuan3d/paint/render.pycomfy/ldm/hunyuan3d/paint/unet.py
📚 Learning: 2026-05-04T18:30:37.579Z
Learnt from: Talmaj
Repo: Comfy-Org/ComfyUI PR: 13655
File: comfy/model_detection.py:907-917
Timestamp: 2026-05-04T18:30:37.579Z
Learning: In ComfyUI’s internal supported model implementations (comfy/supported_models_base.py and comfy/supported_models/*.py), ensure model classes do not override matches() in their own class bodies. All supported models should use BASE.matches() for backward compatibility; if a future change introduces a matches() override in a subclass, treat it as a backward-compatibility risk and require additional review/testing to confirm behavior remains consistent with BASE.matches().
Applied to files:
comfy/supported_models.py
📚 Learning: 2026-03-04T14:05:31.426Z
Learnt from: jtydhr88
Repo: Comfy-Org/ComfyUI PR: 12757
File: comfy_extras/nodes_custom_sampler.py:1069-1089
Timestamp: 2026-03-04T14:05:31.426Z
Learning: In the ComfyUI sampling pipeline, treat percent_to_sigma(0.0) as a sentinel value (999999999.9) that means starting from pure noise. This is consistent with BasicScheduler via calculate_sigmas. The SamplingPercentToSigma node’s return_actual_sigma flag differentiates this sentinel from sigma_max. Reviewers should not flag CurveToSigmas or similar nodes that rely on percent_to_sigma as bugs; downstream samplers are expected to handle the sentinel correctly. When reviewing related sampling-related code, assume this sentinel semantics unless there is explicit handling for a real sigma_max.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
📚 Learning: 2026-04-04T13:29:15.653Z
Learnt from: kijai
Repo: Comfy-Org/ComfyUI PR: 13258
File: comfy_extras/nodes_frame_interpolation.py:151-189
Timestamp: 2026-04-04T13:29:15.653Z
Learning: In this ComfyUI codebase, node `execute()` inference is already run under a global `torch.inference_mode()` context established in the execution engine (e.g., `execution.py` around line ~732). During review, avoid recommending changes that wrap node inference loops in `torch.inference_mode()`—it is already applied, so such suggestions are likely redundant.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
📚 Learning: 2026-05-09T18:40:40.199Z
Learnt from: kijai
Repo: Comfy-Org/ComfyUI PR: 13813
File: comfy_extras/nodes_wandancer.py:868-872
Timestamp: 2026-05-09T18:40:40.199Z
Learning: When building video/temporal decoding nodes that call ComfyUI’s VAE.decode (comfy/sd.py), leverage VAE.decode’s existing VRAM-aware chunking along dim 0. Reshape or transpose the latent so the temporal dimension T is folded into dim 0 (e.g., transform a latent of shape [B, T, C, H, W] into [B*T, C, H, W] before calling vae.decode). This lets VAE.decode do chunked decoding without needing an explicit per-frame loop inside the node itself.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
📚 Learning: 2026-05-20T00:10:14.673Z
Learnt from: Pauan
Repo: Comfy-Org/ComfyUI PR: 13997
File: comfy_extras/nodes_string.py:12-25
Timestamp: 2026-05-20T00:10:14.673Z
Learning: In the ComfyUI `comfy_extras/` codebase, some nodes intentionally ship with a default input string that references parameters that may not yet be connected. If the default would raise a `KeyError` (e.g., examples like `MathExpression` default `a + b`, or `StringFormat` default `{a}` with `min=0` and autogrow inputs), treat it as an intentional “hint default” UX pattern, not a bug. During review, do not flag this behavior or recommend changing `min` to `1` or altering the default to an empty string solely to avoid the `KeyError`.
Applied to files:
comfy_extras/nodes_save_3d.pycomfy_extras/nodes_hunyuan3d_paint.py
🪛 ast-grep (0.44.1)
tests-unit/comfy_test/paint_parity/compare_reference.py
[warning] 64-64: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(args.out, "w", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
tests-unit/comfy_test/paint_parity/capture_reference.py
[warning] 66-66: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "r", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
[warning] 94-94: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(os.path.join(args.unet_dir, "config.json"), "r", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
tests-unit/comfy_test/paint_parity/bundle_format.py
[info] 67-67: use jsonify instead of json.dumps for JSON output
Context: json.dumps(v)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
tests-unit/comfy_test/test_hunyuan3d_paint_render.py
[warning] 385-385: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "rb")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
[warning] 529-529: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "rb")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
[warning] 617-617: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(path, "rb")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
🔇 Additional comments (47)
comfy/ldm/hunyuan3d/paint/render.py (7)
41-100: LGTM!
107-149: LGTM!
155-178: LGTM!
311-386: LGTM!
392-427: LGTM!
433-534: LGTM!
537-598: LGTM!comfy_extras/nodes_hunyuan3d_paint.py (5)
31-56: LGTM!
100-124: LGTM!
165-225: LGTM!
250-294: LGTM!
59-68: 🎯 Functional CorrectnessNo change needed
The
330cutover matches the referencecam_mappingimplementation rather than being a transcription error from a270boundary.> Likely an incorrect or invalid review comment.nodes.py (1)
2450-2450: LGTM!comfy_api/latest/_util/geometry_types.py (1)
48-50: LGTM!comfy_extras/nodes_save_3d.py (2)
80-81: LGTM!Also applies to: 93-94, 129-140, 151-159, 169-169
286-290: LGTM!Also applies to: 413-433
comfy/ldm/hunyuan3d/paint/attention.py (1)
20-55: LGTM!Also applies to: 58-84, 90-131, 134-258, 265-311
comfy/ldm/hunyuan3d/paint/unet.py (1)
22-131: LGTM!Also applies to: 134-258, 261-300, 303-423, 429-521, 524-563, 569-658, 660-741
comfy/latent_formats.py (1)
778-788: LGTM!comfy/ldm/hunyuan3d/paint/loader.py (1)
13-96: LGTM!Also applies to: 99-121, 124-157
comfy/model_base.py (1)
50-50: LGTM!Also applies to: 2066-2094
comfy/model_detection.py (2)
2-2: LGTM!Also applies to: 727-732
894-900: LGTM!comfy/supported_models.py (2)
1557-1589: LGTM!Also applies to: 2477-2477
30-30: LGTM!Also applies to: 1920-1948, 2488-2488
comfy/ldm/hunyuan3d/paint/__init__.py (1)
1-4: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint.py (9)
1-36: LGTM!
55-82: LGTM!
85-148: LGTM!
151-179: LGTM!
182-224: LGTM!
227-297: LGTM!
300-340: LGTM!
343-374: LGTM!
377-445: LGTM!tests-unit/comfy_test/test_hunyuan3d_paint_render.py (1)
36-83: LGTM!Also applies to: 94-108, 114-135, 159-245, 251-291, 297-379, 385-442, 448-624
tests-unit/comfy_test/test_hunyuan3d_paint_conventions.py (1)
55-132: LGTM!Also applies to: 142-176, 182-304, 306-368
comfy/ldm/hunyuan3d/paint/CONVENTIONS.md (1)
1-104: LGTM!tests-unit/comfy_test/paint_parity/README.md (1)
1-57: LGTM!tests-unit/comfy_test/paint_parity/bundle_format.py (1)
33-62: LGTM!Also applies to: 65-116
tests-unit/comfy_test/paint_parity/capture_reference.py (1)
36-120: LGTM!tests-unit/comfy_test/paint_parity/compare_reference.py (1)
39-72: LGTM!tests-unit/comfy_test/paint_parity/goldens/tiny_golden.safetensors (1)
1-1: LGTM!tests-unit/comfy_test/paint_parity/harness.py (1)
19-49: LGTM!Also applies to: 52-107, 110-124
tests-unit/comfy_test/paint_parity/make_goldens.py (1)
10-33: LGTM!tests-unit/comfy_test/parity_report.md (1)
6-16: 📐 Maintainability & Code Quality | 💤 Low value
act/unet.conv_in/conv_outdeltas don't line up withoutput/noise_pred.
output/noise_predisconv_out's tensor in a different layout, yet its max abs diff (3.278e-06) is two orders of magnitude smaller thanact/unet.conv_out(4.888e-04). That's only explainable if the hook captured a different invocation on one side (e.g. a reference/ref-latent pass firing the same module twice, with the last call winning). Worth a one-line note in the report so the per-block rows aren't read as the port's error budget.tests-unit/comfy_test/test_hunyuan3d_paint_parity.py (1)
31-67: LGTM!
MESH is public comfy_api surface that custom nodes construct directly, so adding texture_mr before vertex_counts silently rebound every following positional argument: an eight-positional caller landed vertex_counts in texture_mr and unlit in face_counts, which slips past the paired-counts assert and hands SaveGLB a count tensor to treat as a texture. All in-tree callers already pass these by keyword, so moving the new optional parameter to the end restores the previous positional contract at no cost.
The MR buffer was concatenated into the BIN chunk unconditionally, but the bufferView, image and texture that reference it are only emitted alongside baseColor. A mesh carrying texture_mr with no texture therefore shipped a padded PNG that nothing points at, counted in the buffer byteLength and unreachable to any viewer. glTF hangs metallicRoughness off the same material as baseColor, so there is no meaningful MR-only material to emit here; not encoding it is the honest outcome.
…guidance Returning conds_out unchanged when the latent is not 5D, or when its view axis is not a multiple of the camera count, quietly downgraded per-view guidance to plain scalar CFG. The sampler still produced an image, just a subtly wrong one, with nothing in the log to say so.
_init_weights seeded each parameter from hash(name), but str hashing is salted per process unless PYTHONHASHSEED is pinned, so the "seeded" init drew different weights on every run. The tests that assert finite numerics through the deep net therefore had run-dependent inputs, and any failure would have been unreproducible. The loop already sorts the parameters, so its index is a stable seed source. Also drop the now-dead `if cpu_patch` branch left by making the device-move patch unconditional, and hoist the safetensors import in compare_reference, which is a hard dependency there rather than an optional backend.
learned_text_clip_* and learned_text_clip_ref are always supplied by the checkpoint - the loader rejects a file missing any diffusion_model key - so zero-filling them only costs an initialisation pass over weights that are about to be overwritten.
chunk_id is derived from a cumulative sum, so it is non-decreasing and each chunk is already a contiguous range of faces. Testing chunk_id == c per chunk walked all Fn faces n_chunks times; at the documented 1M-face envelope that boundary search alone cost ~685 ms, against ~0.4 ms for one searchsorted. Output is unchanged: face_id and barycentrics are bit-identical to the previous implementation, and stay bit-identical across chunk_area 256, 4096 and 4M on a mesh mixing tiny triangles with a frame-spanning one. Also soften the memory note above MAX_RESOLUTION. The chunk budget is applied at face boundaries, so it bounds a typical mesh but not a single very large or degenerate triangle, whose bounding box is still expanded in one go.
Rasterization and UV interpolation depend only on the geometry and cameras, which both bakes share, so baking the two maps separately repeated the expensive half of the work. bake_multiview is already generic in channel count, so stacking the two three-channel view sets and splitting the result needs no change to the baker itself. The accumulators are per-channel, so this is exact rather than an approximation: both output textures are bit-identical to the two-pass result. The returned mask is derived from the geometric weight accumulator alone, which is why the two passes were already producing the same mask. Measured 1.94x on a 6-view 512px bake, at identical peak accumulator size - the two-pass version had to hold the first baked texture while baking the second.
…unction class list
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- material self-attention consumed a (B,V,M,...) interleaved layout and its output stack was reshaped as if material-major, scrambling views/materials - reference attention packed concatenated value channels head-mixed instead of the trained head-first M*dim_head slices - learned_text_clip_ref was used raw in compute_reference_bank, breaking on offloaded weights; cast at use with comfy.ops.cast_to_input Tiny Tier-1 golden regenerated. Tier-2 vs real hunyuan3d-paintpbr-v2-1 weights now passes (noise_pred max abs diff 8.7e-06). Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Clean-room rewrite of Hunyuan3D 2.1 paint tainted surfaces
|
I tested your commit, @jethac, it seems to work (I could have tried to get a better output, I suppose, but it was late and I just wanted to check if I understood where to take the models, how to convert them and then if they worked).
Input and output:
Workflow overview (same as the link above, with added colors for me):
Edit:No errors in console (I just wanted to make this known). Console outputEdit 2, other info:Thanks for the contribution! ❤️🚀 |
|
Thanks for taking a look! I love your choice of model 😄 |
|
The existing PR now carries the specification-only native rewrite at |
|
@jethac, would you consider making an extension with the same code, to use in the meantime until this pr gets merged? |
|
@GiusTex sounds like a good idea, i'll do it! |
|
Thanks! |
|
I tried Pixal3d but for some reason I get a messed up shape, which then produces a messed up refined shape and messed up texture; I saw that hunyuan 2.1 doesn't produce detailed views, but in another extension it was used, so it was a bit for completeness. |
Interesting, I would be curious to see what results you get to see how better they are and where we would need to improve. Is there anything you could share please? |
|
Sure, I'll upload code and workflow today when I get to the computer. I want also to clarify all I did (together with Claude) was just a bridge between comfyorg trellis2 models and visualbruno trellis2 multiview custom samplers; they don't work with pixal3d (they don't pass the proj_pack) since it's already implemented by comfyui Edit: |



Summary
This PR supersedes the older implementation with a native Hunyuan3D 2.1 mesh-paint rewrite. It adds the torch-native multiview PBR UNet, renderer/rasterizer/baker, ComfyUI model integration, sampler/scheduler nodes, and textured GLB metallic-roughness save support. The implementation uses the standard ComfyUI sampler/core machinery; it is not an API-node path.
The optional DINO input is intentionally omitted from the tested path. The rewrite also includes PBR mesh/save fixes and is compatible with current upstream
master(15eb748b).Provenance
The rewrite was produced as a specification-only clean-room implementation without access to Tencent's source or the prior implementation. The specification was the public model/checkpoint contract and ComfyUI interfaces. Numerical fixes are recorded in PR #4, including the 33d1f4d changes; the associated review discussion is here. Reference validation is a separate engineering result and does not imply source access. Model weights remain separately licensed artifacts; this PR contains no weights.
Current validation
2d1c6623efd536e2bfc960eeeedd571ce5df68dd; production runtime isc588e42b15adf4c5f36dd7c55becde8398ee2388.15eb748b.472c653bfb7a688d8f0737ab61efa7c6b728acb5091057b87074928242ea2ada) with finite albedo/MR and a valid two-texture PBR GLB.The older audit's RTX 3090 result and claims belong to the superseded head and are historical only; the 33d1f4d RTX 3090 result is likewise historical. Astra accepted the code, merge, runtime, and test fixes. No new numerical reference-parity capture was performed for this rewrite. DINO, LoRA, device-retargeting, and other-hardware behavior remain unclaimed. Maintainer/CI review and merge decisions remain pending.