* docs+tooling: VAE user guide + versioning ref + 3 skills + preflight CI
Documentation
- New user-guide tree: docs/user_guide/nodes/radiance_koolook_v2_3_3/
with README, per-node pages for Easy_hdr_VAE_encode/decode, an
encode/decode pairing guide (4 worked examples + ASCII connectivity
diagram), and an HDR modes deep-dive (per-pixel comparison table).
Folder name mirrors the code path under forks/radiance_koolook/versions/.
- New cross-cutting reference: docs/reference/versioning.md explains the
three independent version axes (pack version, fork wrapper version,
upstream pinned commit), when each one bumps, and which skill/doc
owns it. Plus the v1/v2 node-ID suffix policy.
- Cross-links updated in docs/user_guide/README.md, docs/reference/
README.md, docs/maintainers/README.md.
Skills (all under .claude/skills/)
- docs-sync — controlled find-and-replace for version tags across docs,
code, and manifests; --scope and --dry-run flags.
- menu — lists all project skills with one-liners.
- preflight-release — companion doc for tools/preflight_release.py.
Pre-flight tooling
- tools/preflight_release.py — four checks, exit-code-driven for CI:
(1) static AST extraction of NODE_CLASS_MAPPINGS keys (no torch needed),
(2) stub-VAE dispatch test verifying all 5 rank/VAE-type branches,
(3) drift check against ComfyUI-Manager's extension-node-map.json
(catches the issue #44 phantom-nodes class of bug automatically),
(4) saved-workflow regression check across tests/workflows/*.json.
- .github/workflows/ci.yml — new "Pre-flight Release" job runs checks
1, 2, and 4 on every PR; check 3 (manager-meta) skipped pending the
upstream issue #44 fix.
- tests/workflows/ — 2 starter fixtures (Depth-Anything3, Hires-FIX-wanT2V)
+ README documenting the contribution convention. Coverage grows as
new fixtures are added; no code changes needed.
All four offline pre-flight checks pass on this branch. The
manager-meta check correctly identifies the 39 phantom IDs documented
in issue #44.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(preflight): satisfy ruff lint + bandit security gate
* fix(preflight): address blocking review findings
Three fixes from /review-pr feedback on this PR:
1. Sanitize tests/workflows/*.json — removed 4 unique absolute paths that
leaked internal job/client info ('baconx/Toy-Hix/9110',
'menneskehavn_3029', etc.). Replaced with placeholders like
'path/to/sequence_a' and 'path/to/source_video'. Both fixtures still
parse as valid JSON; grep for the old patterns returns zero hits.
2. Broaden the Koolook-ID heuristic regex from '^easy_[a-z]' to
'^easy_[A-Za-z]'. The old pattern excluded 'easy_ImageBatch' (capital I
after the underscore), which would have silently bypassed the
workflow-fixture stability check for that node. Verified the new
pattern correctly matches it.
3. Wrap check_dispatch() body in try/finally and track every sys.modules
key the function injects in a list, so cleanup runs on the success
path AND on any exception during exec_module / VAE-constructor
execution. Previously only the three torch* stubs were popped, never
the three _pf_pkg* entries — and even those weren't popped on
exception paths. Verified zero leaked modules after the function
returns.
The five dispatch test cases were factored into a helper
_check_dispatch_run_cases() so the try/finally wrapping stays focused on
module injection.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(preflight): address remaining review findings
Follow-up to 7844037 — picks up all the HIGH / MEDIUM / LOW review
findings that were deferred. Pre-flight still passes locally.
HIGH
- Extract check_dispatch (~195 lines) to tools/_preflight_dispatch.py.
Main script drops from 680 → 508 lines. Module exposes a single
run(verbose, repo_root) -> (bool, list[str]) entry; main script keeps
the [2/4] header + PASS/FAIL line.
- Install _HttpsOnlyRedirectHandler that re-validates each redirect
hop's scheme. Closes the gap that urlopen would otherwise follow a
30x to http:// or file:// silently. The Bandit B310 suppression
comment now accurately describes the protection.
- check_static docstring now honestly states it only walks
NODE_CLASS_MAPPINGS literal dicts and does NOT apply
NAMESPACE_SUFFIX / SKIP_VERSION_SUFFIX logic. Notes that the workflow
check (4) is the safety net that surfaces drift the day a non-skipped
ID lands.
- check_workflows now FAILS when the fixtures dir exists with a README
but contains no *.json files — previously silently SKIPPED. If
someone deletes fixtures or typoes the dir, that's a regression in
test coverage and should fail loudly.
MEDIUM
- check_manager_meta validates the upstream entry shape before diffing.
Previous code silently produced an empty set if the schema changed,
reporting every one of our IDs as 'missing'. Now SKIPs with a clear
message when shape is unexpected.
- check_workflows accumulates total_koolook_refs inside the main loop;
drops the redundant second-pass that re-read every fixture file just
to compute the summary count.
- _extract_workflow_node_types uses explicit detection: a canvas-format
file with nodes: null no longer falls through to API-format and pulls
class_type from unrelated keys.
- check_static return type simplified from (bool, set, list) to
(bool, set). Third element was discarded at every call site.
- check_workflows now does two-pronged Koolook-ID matching: heuristic
(catches drift even if static missed an ID) plus actual_ids (catches
IDs that don't fit the heuristic, e.g. a future Koolook node without
Easy / easy_ / koolook in its name).
LOW
- ANSI escape codes named in a constants dict (_ANSI["green"] etc.)
instead of bare string literals.
- Removed dead 'cases: list[tuple[str, callable]] = []' initializer
(was shadowed three statements later).
- check_static's per-ID listing now gated behind --verbose, matching
check_dispatch and check_workflows.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(sidebar): add curated nodes sidebar tab with favorites
New "Curated Nodes" sidebar tab. Shows Koolook nodes auto-grouped by
subcategory under a "Nodes (favorites)" root. Users add favorites from
any installed pack from inside ComfyUI via:
- "+" button: adds the currently selected canvas node(s)
- Right-click any canvas node -> "Add to Curated Sidebar"
Picks persist in browser localStorage (per-browser, survives ComfyUI
restarts). Hover any entry -> "x" to remove. Search filter auto-expands
all folders so matches stay visible; pack/category folders are
collapsed by default otherwise to keep the panel compact.
"Download" export button copies current picks as JSON suitable for
web/curated_defaults.json -- committed to ship as the package's
defaults. On first ComfyUI load with empty localStorage, the seeder
reads curated_defaults.json into localStorage so fresh installs get the
curated set pre-loaded. Existing users keep their localStorage
untouched.
Pure JS, no build step. Uses the documented
app.extensionManager.registerSidebarTab API (stable since
ComfyUI_frontend v1.2.4).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(sidebar): document curated-defaults workflow + seed initial 9 picks
Adds docs/maintainers/curated-sidebar.md covering the full Export ->
paste -> commit flow for shipping distributed favorites with the
package, including storage-key reference, reset procedure, and the
intentional "seed once per browser" semantics.
CLAUDE.md gets a short pointer so the trigger ("update curated
defaults" or pasting an exported picks JSON) is discoverable on the
agent side too. Maintainer docs index linked.
Seeds web/curated_defaults.json with the maintainer's first 9 picks
(GetImageSizeAndCount, GetNode, ImageScaleBy, LoadEXR, NukeConstant,
NukeOCIOColorSpace, SaveEXRFrames, Text Multiline, easy showAnything).
Fresh installs from this version forward will get them pre-loaded into
their localStorage on first ComfyUI launch; existing users' picks are
untouched.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(sidebar): trim curated-sidebar.md to a one-screen quick reference
Drops the verbose data-flow diagram and the localStorage-vs-userdata
rationale. Keeps the four action steps, the storage-key map, the reset
block, and the four "things that surprised us" footnotes capturing the
non-obvious bits (paste is manual, other users can't reach the repo,
seed-once-per-browser, no publish on web/ pushes). 81 lines removed,
20 added; same file path so existing links still resolve.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(sidebar): workflows section with archive + iteration docs
Adds a Workflows section to the Curated Nodes sidebar tab, sharing the
search field and tree pattern with the existing nodes feature.
Capabilities:
- Save entire canvas or current selection as a workflow.
- Save modal: New name / Use existing name (archive previous) /
Modify existing name. The Workflow-name field is shown only when
needed; "Base on existing" dropdown drives prefill for Use/Modify.
- Auto-archive on same-name save: previous version renamed with
timestamp suffix and flagged archived; new entry takes the slot.
Archive sub-folder appears in each directory only when populated and
is rendered above the active list, so the latest sits at the bottom.
- Right-click on workflow: Load / Rename / Move to other directory /
Move to archive (or Restore from archive) / Delete.
- Right-click on directory: Rename / Delete (with confirm if non-empty).
- Loading a workflow names the tab via loadGraphData's 4th arg
(verified against ComfyUI_frontend src/scripts/app.ts) so the tab
flips from "Unsaved Workflow (N)" to the saved name.
Storage: ComfyUI /userdata/koolook_workflows.json (primary), with a
localStorage fallback if /userdata is unreachable. Distributed defaults
seeded from web/workflow_defaults.json on first ComfyUI load with empty
workflow data -- same one-time-per-install pattern as
curated_defaults.json.
Other panel changes:
- Three labeled rows above the tree (search; NODES action bar;
WORKFLOWS action bar), with thin dividers between them and before
the tree.
- Folder expansion state preserved across re-renders via a pathStates
Map; saving never collapses the directory you were viewing.
- Alphabetical (case-insensitive) sort everywhere via a single
compareNames helper -- pack names, subcategories, directories,
workflow names, dropdown options.
- "Use existing name (archive previous)" action label includes the
parenthetical hint about archive behavior.
Docs:
- New docs/maintainers/dev-iteration-loop.md captures the
dev-sync->restart->verify pattern, agent trigger phrases, persistence
boundaries, and push/publish gates. First read when returning to UI
work after a break.
- New docs/maintainers/workflows-sidebar.md covers workflow storage,
action semantics, archive behavior, and reset procedure.
- docs/maintainers/README.md indexes both.
- CLAUDE.md "dev-sync" section now points at the iteration-loop doc.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(sidebar): address review findings — seed gating + commit checks
Targets the data-integrity findings from the multi-agent PR review:
- BLOCKING: seed flag is now only set after the underlying save/persist
succeeded. `saveUserPicks` returns a boolean; both seeders bail out
(leaving the flag unset for next-load retry) on storage failure.
Previously a transient storage failure during first-load could
permanently strand a user with an empty store and the seeded flag set.
- BLOCKING: `normalizeWorkflowsStore` now strictly validates each
workflow entry — drops entries missing a graph object, coerces
`archived` to a strict boolean (so a stray "false" string can't
accidentally hide a workflow), and logs the dropped count.
- HIGH: save handlers now check `commit()`'s return value and surface a
"Save failed" toast when both /userdata and the localStorage fallback
rejected the write. Previously the user saw "Saved" even though
nothing was persisted. The canvas and selection handlers share a
`saveAndToast` helper to keep the failure path consistent.
- HIGH: `saveCanvasBtn` now checks `canvasIsNonEmpty()` before
serializing. A `serialize()` throw is no longer misreported as
"Canvas is empty." — distinct toasts for distinct failure modes.
- HIGH: `loadWorkflowsStore` now logs (instead of silently swallowing)
parse failures on the localStorage fallback, and warns when /userdata
is reachable but a stale fallback blob still exists from an earlier
outage — gives the user a recovery breadcrumb.
- HIGH: `loadUserPicks` logs parse failures so a corrupt picks blob is
visible in the console before the next save overwrites it.
Skipped from the review with rationale:
- multi-tab seed race: sub-second window, both tabs write identical
defaults, no observable wrong state — navigator.locks not worth it
- splitting `koolook_sidebar.js` and decomposing `renderPanel`:
refactor scope, deferred to follow-up
- `loadGraphData` rename comparison: agent's claim was wrong; existing
`wf.filename !== wfName` matches the upstream `filename` shape (bare
name, no extension) we verified earlier against ComfyUI_frontend
v1.44.x source
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(sidebar): second-pass review fixes — rollback, idempotency, corrupt-file handling
Addresses the residual findings from the post-625aa97 review pass.
BLOCKING:
- patchCanvasMenu is now idempotent. Adds a __koolookCuratedPatched
sentinel on LGraphCanvas.prototype so a soft-refresh / re-import
doesn't stack duplicate "Add to Curated Sidebar" entries on every
node's right-click menu. (LGraphCanvas is shared with every other
pack, so non-idempotent prototype mutation was visible globally.)
HIGH:
- persistWorkflowsToServer now returns "server" | "fallback" | false
instead of just true/false. seedWorkflowDefaultsIfNeeded only marks
WORKFLOWS_SEEDED_KEY when the seed actually reached /userdata —
previously a fallback-only seed (when /userdata was unreachable on
first install) marked the user as "seeded" and they would have an
empty server file forever after recovery.
- All 8 commit() callsites that mutate workflowsCache (saveAndToast,
move, archive, restore, rename workflow, delete workflow, rename
directory, delete directory + delete-non-empty-directory, create
directory) now go through a new persistMutation helper that:
- snapshots the cache before mutation
- bails (toast no-op) if mutate returns false
- rolls back the cache + re-renders if commit() returns false
- toasts persistFailedMessage so the user isn't told a write
succeeded when both /userdata and the localStorage fallback
rejected it
Pairs with snapshotCache() helper for explicit snapshot/restore.
- addToMyPicks tri-state ("added" | "duplicate" | "failed") so callers
can distinguish "already in favorites" from "save failed" on
localStorage quota / private-mode failure. Both call sites (the +
toolbar button and the right-click "Add to Curated Sidebar" menu
entry) updated to handle all three states.
- fetchWorkflowsFromServer now distinguishes a network failure from a
parse failure of an existing-but-corrupt /userdata file. Returns
SERVER_FILE_CORRUPT (a Symbol) on parse error; loadWorkflowsStore
surfaces a toast and returns { corrupt: true }; setup() skips
seedWorkflowDefaultsIfNeeded entirely so we don't auto-overwrite a
recoverable-but-unreadable file with stock defaults.
- loadWorkflowOntoCanvas snapshots the current canvas before
app.loadGraphData and restores it on throw. Previously a workflow
with a now-unregistered node type could destroy the canvas partway
through and leave the user with neither the old graph nor the new.
- Stale localStorage fallback detection (when /userdata is reachable
but a fallback blob from a previous outage is still present) now
surfaces a toast in addition to the console warning, so a user who
doesn't have DevTools open gets a recovery breadcrumb.
MEDIUM:
- Modal escape-handler leak fixed via centralized close(). Every
dismissal path (Escape key, overlay click, Cancel/OK calling
overlay.remove()) now tears down the document-level keydown listener.
Existing call sites that use overlay.remove() keep working — the
remove method itself routes through cleanup.
Skipped from the review with rationale:
- subcategoryFor cosmetic mismatch fallback at L1000-1008 — silent
rewrite is rare-path defensive, not load-bearing; defer.
- Optional toast on seedDefaultsIfNeeded storage failure — console
warning is sufficient for a development-time scenario; defer.
- File size / module split (1864 lines) — refactor scope, deferred to
follow-up per prior commit message.
- Magic sentinel strings ("__new__", action enum strings) — pure
cleanup; defer.
- dataset.expanded boolean-string compare — pathStates Map already
carries booleans; cleanup defer.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Renames the [0.1.10] CHANGELOG section to [0.2.0] (the rolled-forward
work from PR #42 was never published as 0.1.10) and bumps pyproject.toml
to match. Minor bump signals the meaningful surface changes:
- New encode return tuple shape (LATENT, STRING, IMAGE).
- Six new cinema log color spaces + ACES 2065-1 + Rec.2020 Linear.
- Compress (Log) HDR mode with per-profile soft-shoulder + log-domain
highlight denoise.
- New latent_sampling parameter (sample / mean / mode).
- Behavior change: exposure now applied in linear space for non-Raw
source spaces (was a code-domain multiplier before).
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Combines two changes to Easy_hdr_VAE_encode/decode (Koolook v2.3.3 fork):
1. Rank-aware dispatch + 5D-output normalization. 5D video tensors paired
with a 2D image VAE are iterated frame-by-frame on encode (stack on
dim=2) and per-frame decoded on decode (cat on dim=0). 5D output from
3D-aware video VAEs (Wan 2.2, Hunyuan, CogVideoX, LTX — exposed via
`vae.latent_dim == 3`) is reshaped (-1, H, W, C) to ComfyUI's standard
IMAGE batch, mirroring stock VAEDecode at nodes.py:303-304. Fixes the
"1056x41 count=1" symptom where 41-frame Wan 2.2 sequences collapsed
to a single squashed image; SaveImage now writes one PNG per frame.
2. Cinema color surface ported from upstream Radiance v2.3.3 (without the
broken 4K cosine-blend tile engine that motivated the slim fork in the
first place). 12 source/target spaces including six cinema log curves
(ARRI LogC3/LogC4, Sony S-Log3, Panasonic V-Log, DaVinci Intermediate,
RED Log3G10) plus ACES 2065-1 and Rec.2020 Linear. Compress (Log) HDR
mode pairs encode-side log-curve encoding with decode-side per-profile
soft-shoulder + log-domain highlight denoise for HDR-clean roundtrips.
New latent_sampling parameter (sample/mean/mode). Alpha now surfaces
as a real third IMAGE return on encode (the previous flag was a no-op).
Exposure is now applied in linear space for all non-Raw source spaces;
Raw source still does a raw-domain multiplication so users who know what
they are feeding the VAE keep their bytes intact.
Helpers extracted to forks/radiance_koolook/versions/v2_3_3/color_helpers.py
(log curves, soft-shoulder, log-denoise, sampling-mode helper, color
matrices, dispatch tables) so nodes_vae.py stays focused on node wiring.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per maintainer direction: Easy_Version was a one-line node that turned
an INT N into the string `vNNN` (zero-padded). The first trivial node
ever written for the pack, never used in production workflows. Removed
to keep the pack's surface focused on the higher-value nodes.
Anyone needing the exact behavior can either inline `f"v{N:03d}"`
downstream of an INT primitive in their workflow, or pull a more
general string-format node from KJ Nodes / ComfyUI-Custom-Scripts.
BREAKING for any saved workflow that references the `Easy_Version` ID
(node will fail to load on import). Same migration shape as the v0.1.5
__koolook_v1_0_1 cleanup.
Also rolls the [Unreleased] PR #39 LATENT-dict-wrap fix into [0.1.9]
so it ships in the same release.
Touched:
- Deleted: k_easy_version.py
- __init__.py: removed version_mappings / version_display imports + merges
- README.md: removed node-table row, Pipeline category list update,
Features bullet, Usage section, Node Code Overview line, install
category list — Easy Version no longer mentioned anywhere
- pyproject.toml: 0.1.8 -> 0.1.9
- CHANGELOG.md: [0.1.9] entry covering the removal + the carried-over
PR #39 fix
Net effect: pack drops from 8 nodes to 7. Koolook/Pipeline subfolder
now has only EasyAIPipeline.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
For one-line fixes that don't deserve their own version bump, copy the
runtime files into the maintainer's live ComfyUI custom_nodes folder
directly instead of going through the publish-and-update round-trip.
What this adds:
- `scripts/sync_to_dev.py` — minimal Python (no third-party deps); reads
`KOLOOK_COMFYUI_DEV_PATH` from the environment (auto-loads `.env` at
the repo root); copies the curated set of runtime-relevant files
(top-level `k_*.py`, `__init__.py`, `config.json`, `forks/`, `web/`)
while skipping CI/docs/metadata. Errors out cleanly when the env var
is unset — never guesses a path.
- `.env.example` entry `KOLOOK_COMFYUI_DEV_PATH=` with explanatory
comment, matching the existing `KOLOOK_*` convention.
- `CLAUDE.md` section documenting the trigger phrase `dev-sync` so a
fresh agent session knows to invoke the script when the maintainer
asks for it.
This is a development-loop convenience only — anything worth shipping
still goes through the normal PR + release flow.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
vae.encode() returns a raw torch.Tensor, but ComfyUI's LATENT type is
contractually `{"samples": tensor}`. The encoder was returning the bare
tensor, so wiring it into KSampler triggered:
IndexError: too many indices for tensor of dimension 5
at `latent_image = latent["samples"]` in common_ksampler. Python 3.11+
traceback markers point right at the subscript. With Wan 2.2's 5-D
(B, C, T, H, W) latent, the string-on-tensor index goes through PyTorch's
__getitem__ and surfaces as IndexError rather than TypeError.
Fix matches upstream ComfyUI's VAEEncode pattern:
return ({"samples": t}, )
The decoder side already destructures `samples["samples"]` correctly,
so it's unaffected.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Three small UX fixes from the v0.1.7 post-release inspection:
1. Categories: the catch-all `Koolook/VFX` subfolder is replaced with
three more granular ones:
- Easy_Version, EasyAIPipeline -> Koolook/Pipeline
- easy_ImageBatch -> Koolook/Image (joins EasyResize)
- Easy_hdr_VAE_encode/decode -> Koolook/VAE
2. Easy_hdr_VAE_encode / Easy_hdr_VAE_decode display names: previously
the display equalled the node ID (`Easy_hdr_VAE_encode`) so the user
couldn't find them by typing `koolook` in the node-add search filter
— they were registered correctly but invisible to the filter. Now:
"Easy_hdr_VAE_encode" -> "Easy HDR VAE Encode (Koolook)"
"Easy_hdr_VAE_decode" -> "Easy HDR VAE Decode (Koolook)"
Matches the title-case " (Koolook)"-suffixed convention used by the
rest of the pack since v0.1.7.
3. README node tables + categories list updated to match.
Class IDs unchanged everywhere -- saved workflows that reference any of
these IDs continue to load and run unchanged. CATEGORY is purely a UI
hint and only affects the node-add menu hierarchy.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Bundles two changes for v0.1.7:
1. PR #36 (already on main, just rolling [Unreleased] -> [0.1.7]):
suffix all node display names with " (Koolook)" so they group
together in ComfyUI's node-add search. Class IDs unchanged.
2. Docs reorg:
- git mv Glossary.md -> docs/reference/glossary.md
- git mv RELEASING.md -> docs/maintainers/releasing.md
- Three audience buckets under docs/: user_guide/ (end users),
reference/ (lookups), maintainers/ (project ops). Each gets a
short index README.md.
- Top-level docs/README.md as the navigation entry point.
- New: docs/maintainers/registry-api.md captures the Comfy Registry
undocumented version-management API (deprecate/yank/status enum,
auto-deprecation behavior, curl recipes, optional GH Actions
workflow YAML for codified mgmt without exposing the token).
- New: docs/maintainers/node-versioning.md codifies the rules from
the v0.1.5 PR-review discussion for changing INPUT_TYPES /
RETURN_TYPES / class names without breaking saved workflows.
- Imported the existing untracked docs/ images that the maintainer
started locally (node inventory screenshot, Easy Image Batch
helper image).
- Cross-references updated in README.md, CLAUDE.md, the issue
template, and .claude/skills/add-external-fork/SKILL.md.
Root drops from 6 -> 4 markdown files. The four that stay (README,
LICENSE, CHANGELOG, CLAUDE.md) are the ones that *must* live there for
GitHub / Comfy Registry / tooling / Claude Code reasons.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Previously typing "koolook" in ComfyUI's node-add search only surfaced
KoolookLoadCameraPosesAbsolute and the v2.3.3 fork VAE nodes (via their
version suffix). The four other nodes (Easy_Version, EasyAIPipeline,
easy_ImageBatch, EasyWan22Prompt) had display names with no Koolook
marker and so were invisible to that search.
Adds " (Koolook)" suffix to each display name, matching the pattern
introduced in #35 for EasyResize_Koolook. Class keys are unchanged
(per CLAUDE.md "Never rename existing namespaced node IDs"), so saved
workflows keep loading and running unchanged.
Also moves Easy_Version's CATEGORY from "VFX/Utils" to "Koolook/VFX"
so it appears under the same parent folder as the rest of the pack.
No version bump — release with the next tag.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Resolves the genuine `EasyResize` node-ID collision with
`ComfyUI-EasyFilePaths` (orange-triangle warning #8 in
ComfyUI-Manager). Both packs were registering the bare class name
`EasyResize` — load order determined which one a user actually got.
Changes:
- k_easy_resize.py:
- Add SPDX-License-Identifier: GPL-3.0-or-later header.
- Add proper attribution block crediting kijai/ComfyUI-KJNodes
(Resize Image V2, GPL-3.0) as the original interface inspiration,
with a per-feature list of how the Koolook implementation
materially extended the surface (aspect-ratio parser,
keep_proportion modes, mask + composed outputs, device selection,
target/original W/H reporting, color-panel passthrough).
- Register both `EasyResize_Koolook` (canonical, new) AND
`EasyResize` (deprecated alias) IDs pointing at the same class.
Saved workflows using the legacy `EasyResize` ID continue to load
and run; new workflows pick `EasyResize_Koolook` from the search
and avoid the conflict.
- Display name on legacy alias reads `Easy Resize (deprecated, use
'Easy Resize (Koolook)')` to nudge users to switch.
- forks/THIRD_PARTY.md: full attribution entry for KJ Nodes (was
missing — manifest had it as `license: "unknown"` /
`sync_state: "needs-upstream-reference"`). License verified as
GPL-3.0 against upstream `LICENSE` file (same as our pack — no
relicense pressure).
- forks/forks_manifest.yaml: KJ Nodes entry upgraded from
`license: "unknown"` to `license: "GPL-3.0"` +
`license_verified_at`, `status: "inspired_reimplementation"` (more
accurate than `modified`), and the two exposed_node_ids are now
recorded explicitly.
- README.md: node table, category list, "Easy Resize" section, and
Wan-related descriptions all updated to use the new canonical
`EasyResize_Koolook` ID and display name.
- pyproject.toml: 0.1.5 -> 0.1.6.
- CHANGELOG.md: [0.1.6] entry covering the rename + attribution work.
Follows the node-versioning rules from the `node-versioning` discussion
in PR review: rename via alias, never break saved workflows, document
the deprecation in CHANGELOG.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* chore: remove maintainer dev workspaces from git tracking + bump 0.1.4
ComfyUI-Manager was reporting "44 nodes / 13 conflicts" for this pack
because the Comfy Registry's static scanner walks every `*.py` in the
published archive and reads `NODE_CLASS_MAPPINGS` dicts — including
the ones inside vendored third-party clones sitting in two folders
that were never meant to be part of the package:
upscaler_FIX/github_repos/ComfyUI-SuperUltimateVaceTools/
upscaler_FIX/github_repos/ComfyUI-multigpu/
nuke_CAM_exporter/wrapper_FIX/wrapper_fun_camera_*-code/
nuke_CAM_exporter/_Utils-CAM-track/Github-Repos/...
These folders were the maintainer's local debugging / camera-tracking
scratchpads, accidentally committed in Dec 2025 commits ec6a5ff
("Update venv at bX") and 82792e9 ("SuperUltimateVaceTools - fixed
tilling, MultiGPU - fixed torch"). Root `__init__.py` never imported
from them, so ComfyUI runtime loading was unaffected — but the
registry/Manager view was polluted, and we were inadvertently
shipping ~3.7 MB of someone else's GPL/Apache code under our pack
name on every release.
Resolution:
- `git rm -r --cached upscaler_FIX nuke_CAM_exporter` — 70 files
untracked, still on local disk for the maintainer's reference.
- Added both paths to `.gitignore` so they cannot leak back in via
`git add .`.
- Bumped pyproject.toml to 0.1.4.
Same class of issue as the v0.1.2 GPL-3.0 relicense (vendored 3rd-party
in MAIN), but lower risk because none of this code was ever imported,
and removing it doesn't change runtime behavior.
Per CHANGELOG note: maintainer should back up the two folders before
pulling this commit into their main worktree, otherwise `git pull`
will apply the deletions to their working tree (history retains them
either way; recoverable via `git checkout HEAD~1 -- ...`).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* chore(forks): drop v1_0_1 fork entirely + bump 0.1.5
Per user direction (option M from the conversation), removes the entire
forks/radiance_koolook/versions/v1_0_1/ folder — ~5,200 lines, 26
namespaced nodes — that wrapped Radiance v1.0 classes nobody used.
The wrappers were vestigial:
- 22 of them were verbatim copies of upstream Radiance v1.0 classes
with no Koolook modifications (ImageToFloat32, Float32ColorCorrect,
HDRExpandDynamicRange, HDRToneMap, ColorSpaceConvert, etc).
- The 1 genuinely-modified wrapper (RadianceOCIOColorTransformV2 with
multiframe + alpha preservation) was a derivative the Koolook author
doesn't use.
- The 3 Koolook-original entries (LoadImageEXRSequence, RadianceVAEEncode,
RadianceVAEDecode) were either unused (LoadImageEXRSequence) or
superseded in v2_3_3 (the VAE pair → Easy_hdr_VAE_encode/decode).
After this release the package exposes 8 nodes (down from 34):
Easy_Version
EasyWan22Prompt
EasyResize
EasyAIPipeline
easy_ImageBatch
KoolookLoadCameraPosesAbsolute
Easy_hdr_VAE_encode
Easy_hdr_VAE_decode
This is BREAKING for anyone who saved workflows using the
__koolook_v1_0_1 namespaced IDs — none of those resolve anymore.
Migration: install upstream Radiance directly for the HDR/EXR/OCIO
functionality, and use Easy_hdr_VAE_encode/decode for VAE work.
Source code recoverable via git history.
Bundled into release/v0.1.4-prep (now v0.1.5) so PR #34 ships the
registry-hygiene fix AND the scope cleanup as one coherent release.
Touched:
- Deleted: forks/radiance_koolook/versions/v1_0_1/ (5 files)
- Updated: forks/radiance_koolook/__init__.py (no more v1_0_1 import)
- Updated: forks/forks_manifest.yaml (v1_0_1 entry marked removed)
- Updated: forks/THIRD_PARTY.md (v1_0_1 entry marked removed + GPL note)
- Updated: README.md (Radiance Koolook nodes section + version layout)
- Updated: CLAUDE.md (Radiance v1 policy → Radiance v2_3_3 policy)
- Updated: pyproject.toml (0.1.4 → 0.1.5)
- Updated: CHANGELOG.md ([0.1.5] entry, [0.1.4] marked superseded)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* chore: relicense to GPL-3.0 and backfill upstream attribution
ComfyUI-Koolook v0.1.0 and v0.1.1 shipped under a claimed MIT license
while already incorporating GPL-3.0-derived code from
fxtdstudios/radiance under forks/radiance_koolook/. GPL-3.0 §5(c)
requires the entire combined work to be GPL-3.0 — relicensing the
whole package is the simplest honest fix and aligns with the dominant
license posture of the ComfyUI custom-node ecosystem.
Changes:
- Add full GPL-3.0 LICENSE text at repo root (pyproject.toml already
referenced LICENSE but the file did not exist).
- Update README.md "## License" section to declare GPL-3.0 and explain
the §5(c) implication for downstream users.
- Backfill forks/THIRD_PARTY.md with full attribution entries for the
Radiance v1.0.1 baseline (already in the repo) and the upcoming
Radiance v2.3.3 VAE subset (scaffolded in v0.1.2).
- Update forks/forks_manifest.yaml: set the existing entry's license
field to "GPL-3.0" (was "to_verify_at_source_ref"), add a
license_verified_at field, and pre-register the v2.3.3 VAE entry
with verified license metadata.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(skills): add license-pre-check + port add-external-fork to .claude/skills/
Two skills to prevent the v0.1.0/v0.1.1 license-incompatibility class
of bug from happening again on future forks:
- license-pre-check: blocking compatibility audit run BEFORE any code
is copied or written based on upstream. Reads the upstream LICENSE,
compares against ours via an SPDX matrix, refuses to proceed on
incompatible combinations, and records the result for the manifest.
- add-external-fork: ports the existing .cursor/skills/add-external-fork
procedure to .claude/skills/ so Claude Code can run it directly. The
port adds a mandatory Phase 0 ("run license-pre-check first") and
expands Phase 3c to require GPL §5(a) modification headers on
derived files.
The .cursor/ copy is left in place for Cursor users; the two should be
kept in sync manually until a unifying mechanism is adopted.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(forks): port v2.3 VAE Encode/Decode as slim video-friendly wrapper
Adds forks/radiance_koolook/versions/v2_3_3/ — a slim re-implementation
of RadianceVAEEncode / RadianceVAEDecode under the namespace suffix
__koolook_v2_3_3. Mirrors the input surface of upstream's
RadianceVAE4KEncode / RadianceVAE4KDecode (fxtdstudios/radiance v2.3.3,
GPL-3.0) but deliberately skips the 4K cosine-blend tile engine.
Why skip the tile engine: that pipeline errors with `size of tensor a
(192) must match the size of tensor b (132) at non-singleton dimension
4` when chained into Wan 2.2 video workflows, because the tiler's
spatial layout disagrees with the video VAE's internal temporal-aware
encoding. Modern video VAEs (Wan 2.2, Hunyuan, CogVideoX, LTX) handle
their own internal stitching, so the tiler is redundant and actively
breaks the chain.
What ships:
- forks/radiance_koolook/versions/v2_3_3/nodes_vae.py — RadianceVAEEncode
and RadianceVAEDecode classes (~330 lines), rank-agnostic, with a
STRING `debug_info` second return that mirrors the pattern from
v1's RadianceOCIOColorTransformV2.
- forks/radiance_koolook/versions/v2_3_3/__init__.py — applies
__koolook_v2_3_3 namespace suffix and " (Koolook v2.3.3)" display
suffix, mirroring the v1_0_1 wrapper layout.
- forks/radiance_koolook/versions/v2_3_3/UPSTREAM_PIN.yaml — pinned
upstream commit f262f47 + license metadata.
- forks/radiance_koolook/__init__.py — merges v1_0_1 + v2_3_3 mappings.
- pyproject.toml — version bumped to 0.1.2.
- CHANGELOG.md — full [0.1.2] entry covering the license relicense,
the new v2_3_3 fork, the two new skills, and the carry-over RELEASING.md
docs that landed on main since 0.1.1.
Existing __koolook_v1_0_1 nodes are unchanged and remain available for
backward compatibility with saved workflows.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* refactor(forks/v2_3_3): rename VAE nodes to Easy_hdr_VAE_encode/decode + bump 0.1.3
Per user direction, the new video-friendly VAE wrappers are now exposed
under clean Koolook-style IDs and display names — no more
`__koolook_v2_3_3` suffix in the ComfyUI node-add UI:
- `Easy_hdr_VAE_encode` (was `RadianceVAEEncode__koolook_v2_3_3`)
- `Easy_hdr_VAE_decode` (was `RadianceVAEDecode__koolook_v2_3_3`)
Why: when both upstream Radiance v2.3.3 and our pack are installed, both
expose `Radiance VAE Encode` in the search — the Koolook-suffixed
display name still buried "Koolook" at the end of a long line, so users
were likely to mis-pick. The new names lead with the Koolook brand and
the Easy_* family convention used elsewhere in this pack
(Easy_Version, EasyAIPipeline, EasyResize, etc.).
Mechanism: new `SKIP_VERSION_SUFFIX = {...}` set in
`versions/v2_3_3/__init__.py` opts specific IDs out of the auto-suffix.
The version is still tracked structurally (file path) and textually
(file header, UPSTREAM_PIN.yaml, forks/THIRD_PARTY.md). Future
Koolook-original nodes in this fork can opt out the same way; ports of
upstream-named classes still get the suffix by default for collision
safety.
0.1.2 was test-published to the registry with the previous IDs but
never tagged or formally released; bumping to 0.1.3 publishes the
renamed version cleanly. Old 0.1.2 entry retained in CHANGELOG with a
"superseded" note for transparency.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
The v0.1.1 release surfaced two latent gaps:
1. The v0.1.0 tag was on an orphaned merge commit (PR #26 was
re-merged), so `git describe --tags` failed and ComfyUI-Manager
showed the installed version as "unknown".
2. `[tool.comfy] PublisherId` was the placeholder "CristianP", which
does not exist on the Comfy Registry. Every `Publish to Comfy
registry` workflow run since at least Feb 2026 failed with the
misleading `400 "Failed to validate token"`.
Both were the consequence of cutting releases ad-hoc. RELEASING.md
codifies the procedure so future releases follow the same path:
- pre-release validation
- release branch + PR with version bump and CHANGELOG entry
- registry publish validated via workflow_dispatch BEFORE merge
(catches PublisherId / token / version-conflict errors in PR review)
- squash-merge (single commit per release prevents the orphan-tag class)
- annotated tag at the squash-merge SHA
- GitHub Release from the matching CHANGELOG section
- post-release verification (Manager UI + registry status)
Also updates the per-release issue template to mirror RELEASING.md,
and adds links from README and CLAUDE.md so both humans and agents
land on the canonical doc.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
The v0.1.0 tag points to an orphaned merge commit (PR #26 was
re-merged at f7cedf0, leaving the tagged commit 38433a9 outside
main's ancestry). As a result `git describe --tags` failed locally
and ComfyUI-Manager displayed the installed version as "unknown".
Bump pyproject.toml to 0.1.1 and add a matching CHANGELOG entry so
a fresh annotated tag at the current main HEAD restores
version visibility for installs.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* ci: add lint, syntax-smoke, and bandit security gate
Two gating jobs for PRs to main: ruff + python -m compileall ("Lint & Smoke")
and bandit static analysis ("Security Gate"). Bandit excludes vendored sub-trees
(forks/, upscaler_FIX/, nuke_CAM_exporter/).
Pattern lifted from malkuthro/ForgeFlow's CI. Status checks will be wired into
the Protect-main ruleset after first green run on main.
Refs #29
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* ci: exclude vendored sub-trees from lint and smoke
Ruff was flagging 93 errors in upscaler_FIX/github_repos/ComfyUI-multigpu/
(vendored upstream copies). Match bandit's exclude list so lint only checks
this repo's own code.
De-vendoring is tracked separately in #28.
Refs #29
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* chore: remove unused imports, add ruff config
- Drop unused os/json from k_easy_version.py and torch from k_easy_wan22_prompt.py.
- Add [tool.ruff] in pyproject.toml: extend-exclude vendored sub-trees,
per-file-ignores F841 for k_easy_resize.py (intentional symmetry vars
pad_b/pad_r/original_B/original_C are kept for clarity).
- CI workflow simplifies to plain `ruff check .` since config is now centralized.
Refs #29
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Replace ".venv/*" (wrong syntax — only ignores files inside) with
".venv/" so the directory itself is ignored. Add __pycache__/, *.pyc,
*.pyo, and .DS_Store which were missing and previously got tracked.
Companion to a history rewrite that strips .venv/, __pycache__/,
*.pyc, ACES_workflow/, _ComfyUI_workflows/, and _ComfyUI_settings/
from past commits (these trees were already removed from the working
tree in earlier releases but bloated the repo to 235MB; post-rewrite
size ~24MB).
Made-with: Cursor
Squash of 4 commits from docs/readme-sync-current-nodes. Out of scope (tracked in #28): de-vendor upstream copies under upscaler_FIX/ and nuke_CAM_exporter/.
Set project version to 0.1.0, align changelog entries for the new fork/versioning baseline, and include the compact OCIO node ID override for the v1_0_1 Radiance set.
Made-with: Cursor
Remove stale links to deleted docs, document forward tagging conventions for repo/fork/version namespaces, and keep release checklist aligned with current workflow.
Made-with: Cursor
Consolidate fork metadata into forks/, move Radiance custom code into versioned folders, and align external reference naming so upgrades and cross-machine parity are easier to manage.
Made-with: Cursor