- Reject invalid configs in validate_inputs instead of mid-execution: Strict-mode multiple_of above max_res, out-of-range min_res/max_res/ multiple_of, and unknown constraint modes - Share the resolution and multiple_of bounds between define_schema() and validate_inputs() so the widget and the queue-time check cannot drift - Cap the min-res pixel budget at an absolute 64 MP, floored at max_res squared; the multiplier alone permitted ~12 GB outputs at max_res=8192 - Warn on large upscales in Strict mode as well as min-res mode - Pin GitHub Actions by commit SHA on node24-native majors; drop issues:write from the publish workflow and set contents:read on both - Pin Comfy-Org/publish-node-action to the commit @v1 resolves to; the 1.0.1 tag calls `comfy tracking disable`, removed from comfy-cli - Add requirements-ci.txt with pip caching; add ruff config and a CI lint step - Add schema-contract, tooltip, budget, crop-guard and validation tests - Replace typing.Tuple with tuple - Bump version to 2.4.1
6.5 KiB
AGENTS.md — ComfyUI-ConstrainResolution
A ComfyUI node that resizes any image to fit your model's resolution rules: a minimum size, a maximum size, and dimensions guaranteed divisible by 2, 8, 16, 32, or 64. Keeps aspect ratio by cropping a few pixels when needed. No dependencies beyond ComfyUI itself (Python ≥3.10). Built on ComfyUI v3 node API (comfy_api.latest).
Current state
Last verified: 2026-08-24
- Status: released v2.4.1 (
pyproject.toml). Stable and feature-complete for what it sets out to do. Published to the Comfy Registry —.github/workflows/publish_action.ymlfires on apyproject.tomlversion change onmain, so a functional change needs a version bump or it never ships. - Works: both constraint modes (Prioritize Min Resolution, Prioritize Max Resolution strict); divisibility by 2/8/16/32/64 enforced together with the min/max limits so reported width/height always match the output tensor; minimal smart cropping with a configurable crop position; all five resize methods; the full output set (resized image, original passthrough, width, height, final and original aspect ratios).
.github/workflows/test.ymlruns the pytest suite. - In progress: nothing — v2.4.1 polished the v2.4.0 audit:
validate_inputsnow rejects at queue time (Strict-modemultiple_of > max_res, out-of-range resolutions, unknown constraint modes), the min-res memory guard gained an absolute pixel ceiling, large-upscale warnings fire in both modes, CI actions are SHA-pinned with pip caching (requirements-ci.txt, CI-only), and a schema-contract test keepsdefine_schema()in sync withexecute(). - Known gaps / next steps: no batch-specific handling beyond what ComfyUI's own resizer provides; behaviour under extreme aspect ratios is covered by tests but has had little real-world exercise; the README screenshots track v2.3.1 and would need refreshing alongside any visible change.
- Deep docs: none —
README.mdis the user-facing reference andnodes.pyis the whole implementation.
Architecture in 60 seconds
- Single node.
nodes.pycontains the entire feature — one node class, all logic self-contained. - Three rules in one step: min resolution, max resolution, and divisibility. Resize, round, and crop all land on multiples of the chosen number.
- Two constraint modes: "Prioritize Min Resolution" (neither dimension goes below
min_res) and "Prioritize Max Resolution (Strict)" (output always fits in amax_res × max_resbox — hard VRAM cap). - Smart cropping. When an extreme aspect ratio can't satisfy both limits, crops minimally to hit exact dimensions instead of distorting. Crop position configurable (center/top/bottom/left/right).
- Uses ComfyUI's own resizer (
comfy.utils.common_upscale) — results match core resize nodes. Bicubic/lanczos output clamped to valid range to avoid overshoot artifacts. - Rich outputs. Returns resized_image, original_image passthrough, width/height, and both final and original aspect ratios.
Layout
| File / Directory | Purpose |
|---|---|
__init__.py |
ComfyUI custom-node entry point (registers the node) |
nodes.py |
The entire node: resize logic, constraint modes, cropping, validation |
tests/ |
pytest test suite |
conftest.py |
pytest configuration/fixtures |
docs/ |
Images for README |
Build / test / run
# Install via ComfyUI Manager (recommended)
# Search for "Constrain Resolution" in the Manager
# Manual install
cd ComfyUI/custom_nodes
git clone https://github.com/EnragedAntelope/ComfyUI-ConstrainResolution.git
# Restart ComfyUI
# No pip dependencies — Python 3.10+ and ComfyUI itself are the only requirements
# Run tests (conftest.py mocks comfy_api, so no ComfyUI install is needed)
pip install -r requirements-ci.txt
pytest
ruff check .
Conventions & gotchas
- Single-file node —
nodes.pyis the entire feature. Keep it self-contained. - Zero pip dependencies for the pack itself.
requirements-ci.txtexists only for CI (pytest/torch/numpy); never add runtime deps. validate_inputsmust NOT take**kwargs: ComfyUI then skips its own range and combo-option validation for every input on the node (execution.py,validate_has_kwargs). It also skips those checks for each input the function names explicitly, so anything listed in the signature must have its bounds re-asserted inside the function.MIN_RESOLUTION/MAX_RESOLUTION/MIN_MULTIPLE_OF/MAX_MULTIPLE_OFare shared bydefine_schema()andvalidate_inputs()so the widget and the queue-time check cannot drift.- The GitHub Actions pins are commit SHAs; the comment above each one records the version it corresponds to. Keep them on node24-native majors — GitHub warns on, and will eventually stop running, node20 actions.
Comfy-Org/publish-node-actionis pinned to the commit itsv1branch points at — its1.0.1tag is older than that branch and still callscomfy tracking disable, which current comfy-cli does not have. - Divisibility, min/max, and crop dimensions are enforced together — reported width/height always match the actual output tensor.
- Unsatisfiable or memory-exhausting settings raise
ValueErrorrather than returning a zero dimension;calculate_optimal_dimensionsnever returns 0 for a non-empty input. The min-res pixel budget ismax(box, min(box * FACTOR, MAX_OUTPUT_PIXELS))wherebox = max_res ** 2— a size the user's ownmax_respermits is never refused. resize_methoddefaults tolanczos(sharpest). Options: lanczos, bicubic, bilinear, nearest-exact (pixel art/masks), area (big downscales).- When
crop_as_required=Falseandmultiple_of=1, no cropping occurs — keeps every pixel. - The node uses ComfyUI v3 schema (
comfy_api.latest).
Security
This file is public-safe by default. Never add local paths, credentials, API keys, personal data, infrastructure details, or subscription info.
Before pushing, re-read this file and confirm it contains no local paths, credentials, or personal data.
Maintenance
Update rule: When you change the architecture, build/test commands, or conventions, update this AGENTS.md in the same commit. Keep under 200 lines.
CLAUDE.md: One-line shim: @AGENTS.md.
New-repo rule: Create AGENTS.md in the first session a new repo is worked on.
No-overlap rule: Explanatory prose lives in one file. AGENTS.md = agent-facing summary; README.md = human/usage. Identical install commands may be restated verbatim. Explanatory prose must not be duplicated — link instead.