chore(release): clean 0.2.1 registry package

Bump release/0.2.x to 0.2.1 and remove dev-only packaged files while keeping runtime node code unchanged.
This commit is contained in:
malkuthro
2026-05-06 10:19:05 +02:00
committed by GitHub
parent 87ecba2f4d
commit 4cbb0c6231
14 changed files with 15 additions and 871 deletions
-253
View File
@@ -1,253 +0,0 @@
---
name: add-external-fork
description: Set up an external upstream repository as a pinned reference checkout under ../ComfyUI-Forks and register it in MAIN's fork tracking files. Use when adding a new third-party fork, cloning the Radiance (or other) baseline on a fresh machine, registering an external repo for upstream sync work, bumping a fork to a new pinned version (creating a new vX_Y_Z folder), or when the user asks about the forks/ workflow.
---
# Add External Fork
Encodes the ComfyUI-Koolook fork workflow: external upstream code is **never
vendored into MAIN as a whole tree**. Instead, raw clones live in the sibling
folder `../ComfyUI-Forks/`, MAIN tracks them via `forks/forks_manifest.yaml`,
and any modified node code lives in MAIN under
`forks/<package>/versions/<vX_Y_Z>/` with namespaced node IDs.
Use this skill whenever the user wants to:
- clone an external repo for upstream comparison/sync work,
- set up the documented baseline on a fresh machine,
- add a brand-new fork (with or without a wrapper module in MAIN),
- bump a fork to a new pinned version (creates a new `vX_Y_Z` folder).
## Phase 0 — License pre-check (mandatory)
**Before anything else**, run [`license-pre-check`](../license-pre-check/).
It compares the upstream's LICENSE against ComfyUI-Koolook's, refuses to
proceed on incompatible combinations, and records the result. This skill
will not register a manifest entry without a `license_verified_at` field.
The reason this is gate-zero: the v0.1.0/v0.1.1 releases shipped under
claimed MIT while incorporating GPL-3.0 Radiance code, which forced a
retroactive relicense to GPL-3.0 in v0.1.2. Don't repeat it.
## Conventions (do not deviate)
- **Forks root:** `../ComfyUI-Forks` (relative to MAIN). Overridable via env
var `KOLOOK_FORKS_DIR`. Never clone third-party repos *inside* MAIN.
- **External folder names:**
- Pinned baseline → `<repo>-v<version>-koolook` (e.g. `radiance-v1.0.1-koolook`)
- Rolling upstream → `<repo>-main-upstream` (e.g. `radiance-main-upstream`)
- **Local version paths in MAIN:** `forks/<package>/versions/v<MAJOR>_<MINOR>_<PATCH>/`
- **Node ID namespace suffix:** `__koolook_v<MAJOR>_<MINOR>_<PATCH>` (must
match the version folder).
- **Single source of truth:** `forks/forks_manifest.yaml`. Every external
repo must have an entry there.
- **Never rename existing namespaced node IDs** that already appear in saved
workflows. New versions get a new suffix.
## Phase 1 — Discover
Ask (or infer) before doing anything destructive:
1. **Repo URL** (e.g. `https://github.com/fxtdstudios/radiance.git`).
2. **Version label** (e.g. `1.0.1`). Used to name the folder and the
namespace suffix.
3. **Pinned commit** (full hash). If unknown, offer to use the tip of the
upstream default branch and record that hash. Watch out for typo'd or
non-`v`-prefixed tags upstream — pin by commit, not by tag.
4. **Source ref** (tag, branch, or descriptor — e.g. `comfyui (closest
public baseline)`).
5. **Variants needed:**
- pinned baseline only?
- rolling upstream only?
- both?
6. **Wrapper in MAIN?** (yes if Koolook will modify nodes; no if it's
reference-only.)
7. **Modified files** (paths that will live in MAIN under the new
`versions/<vX_Y_Z>/`).
If the request is "set up the baseline on this machine" and a manifest entry
already exists, **read the manifest** to get all of the above instead of
asking — that's the whole point of `forks_manifest.yaml`.
## Phase 2 — External clones (outside MAIN)
```bash
FORKS_ROOT="${KOLOOK_FORKS_DIR:-../ComfyUI-Forks}"
mkdir -p "$FORKS_ROOT"
cd "$FORKS_ROOT"
```
### Pinned baseline
```bash
PIN_DIR="<repo>-v<version>-koolook"
git clone <source_repo> "$PIN_DIR"
cd "$PIN_DIR"
git checkout <pinned_commit>
git rev-parse HEAD # verify, must match pinned_commit
cd ..
```
### Rolling upstream (optional)
```bash
ROLL_DIR="<repo>-main-upstream"
git clone <source_repo> "$ROLL_DIR"
# leave on upstream default branch; do not check out a pin
```
If a clone already exists, do **not** re-clone. Instead `cd` in, fetch, and
verify the commit/branch matches expectations. Report any drift.
## Phase 3 — Register in MAIN
### 3a. `forks/forks_manifest.yaml`
Append (or update) an entry. Mandatory fields:
```yaml
- id: "<package>_v<MAJOR>_<MINOR>_<PATCH>_baseline"
name: "<Human readable name>"
source_repo: "<URL>"
source_ref: "<tag/branch descriptor>"
pinned_commit: "<full sha>"
external_checkout:
relative_path_from_forks_root: "<repo>-v<version>-koolook"
upstream_tracking_path_from_forks_root: "<repo>-main-upstream"
default_branch: "<work branch name, optional>"
local_paths:
- "forks/<package>/versions/v<MAJOR>_<MINOR>_<PATCH>/__init__.py"
- "forks/<package>/versions/v<MAJOR>_<MINOR>_<PATCH>/UPSTREAM_PIN.yaml"
# plus every modified node source file
status: "modified" # or "reference_only"
sync_state: "local-modified-from-upstream"
license: "<SPDX from license-pre-check>"
license_verified_at: "YYYY-MM-DD"
notes: "<what was modified and why>"
```
Bump `updated_at` at the top of the file.
### 3b. `forks/THIRD_PARTY.md`
Add a new entry. Keep it human-readable. Required sections:
- Name + upstream URL + commit/tag
- License (must match `forks_manifest.yaml`)
- Local path(s)
- What changed locally (per class/function, with reasoning)
- Why changed
- Last reviewed date
### 3c. Wrapper module in MAIN (only if `status: modified`)
Create the version folder:
```
forks/<package>/versions/v<MAJOR>_<MINOR>_<PATCH>/
__init__.py # imports node mappings + applies namespace suffix
UPSTREAM_PIN.yaml # mirrors manifest pin for one-file lookup
<copies of modified node source files>
```
`UPSTREAM_PIN.yaml` minimum:
```yaml
source_repo: "<URL>"
source_ref: "<descriptor>"
pinned_commit: "<full sha>"
external_checkout_relative_to_forks_root: "<repo>-v<version>-koolook"
upstream_tracking_relative_to_forks_root: "<repo>-main-upstream"
external_work_branch: "<branch>"
license: "<SPDX>"
```
The version `__init__.py` must:
- import `NODE_CLASS_MAPPINGS` / `NODE_DISPLAY_NAME_MAPPINGS` from each
modified node module,
- apply suffix `__koolook_v<MAJOR>_<MINOR>_<PATCH>` to every ID (and a
display suffix like ` (Koolook v<version>)`),
- optionally register short-ID overrides (e.g. `k_easy_OCIO_v101`).
For each modified source file, prepend a header comment that includes:
- The upstream source path and commit it was derived from,
- A "Modified by ComfyUI-Koolook on YYYY-MM-DD" line (GPL §5(a) requirement
for modified versions),
- The license (which will match the package — currently GPL-3.0).
Then create/update the package entrypoint `forks/<package>/__init__.py` to
merge all version mappings into a single `NODE_CLASS_MAPPINGS` /
`NODE_DISPLAY_NAME_MAPPINGS`, and wire those into the **root `__init__.py`**.
### 3d. Documentation touchpoints
If the new fork changes user-visible behavior or adds/removes nodes:
- Add the new node IDs and categories to `README.md` (node table + categories list).
- Update `CHANGELOG.md` under `[Unreleased]`.
- Mention any new optional Python deps in the README "Compatibility" bullet.
## Phase 4 — Verify
Run from MAIN:
```bash
git status
python -c "import ast; ast.parse(open('forks/<package>/versions/v<vXYZ>/__init__.py', encoding='utf-8').read()); print('SYNTAX OK')"
ls "$FORKS_ROOT"
cd "$FORKS_ROOT/<repo>-v<version>-koolook" && git rev-parse HEAD # equals pinned_commit
```
If any of these fail, stop and report the discrepancy — do not paper over it.
## Phase 5 — Branch & commit
Per the repo's PR workflow, do MAIN-side changes on a feature branch, never
on `main`:
```bash
git checkout -b feat/forks-add-<package>-v<MAJOR>_<MINOR>_<PATCH>
git add forks/ README.md CHANGELOG.md __init__.py
git commit -m "Add <package> v<version> fork wrapper and tracking."
```
External clones under `../ComfyUI-Forks/` are **not** committed to MAIN
(they're outside the repo).
If this fork ships in a release, follow [`docs/maintainers/releasing.md`](../../../docs/maintainers/releasing.md)
for the version bump + tag + GitHub Release flow.
## Bumping an existing fork to a new pinned version
1. Phase 0: re-run `license-pre-check`. Upstream license can change between
versions.
2. Phase 1: keep the existing entry; add a NEW entry with the new version.
3. Phase 2: clone a new pinned folder `<repo>-v<new_version>-koolook` (do
not delete the old one — old workflows may need it for diff).
4. Phase 3: create a new `forks/<package>/versions/v<new_M>_<new_m>_<new_p>/`
and a NEW namespace suffix. **Do not rename existing IDs.**
5. Update `forks_manifest.yaml`, `THIRD_PARTY.md`, README, CHANGELOG.
6. Verify both old and new namespaced IDs still resolve.
## Reference-only forks (no wrapper, no modifications)
Skip 3c entirely. Manifest entry uses `status: reference_only`,
`local_paths: []`. External clone is still useful for inspection/docs.
The license is still recorded — `license-pre-check` is still mandatory.
## Anti-patterns
- ❌ Skipping Phase 0 ("we'll figure out the license later").
- ❌ Cloning third-party repos *inside* MAIN (e.g. `forks/<package>/upstream/`).
- ❌ Reusing an existing version folder for a different upstream commit.
- ❌ Renaming or removing namespace suffixes that already appear in saved
workflows.
- ❌ Editing files inside `../ComfyUI-Forks/<repo>-v<version>-koolook/` and
expecting MAIN to track them — that folder is reference-only.
- ❌ Updating `forks_manifest.yaml` without also updating the matching
`UPSTREAM_PIN.yaml` (and vice-versa).
- ❌ Pinning by tag when upstream has typo'd or non-`v`-prefixed tags. Pin
by commit hash.
-163
View File
@@ -1,163 +0,0 @@
---
name: license-pre-check
description: Run a license-compatibility audit before incorporating any third-party code into ComfyUI-Koolook (or any project that mixes licenses). Use when the user wants to fork a node, vendor a library, port a class from another repo, or add an external dependency. Must run BEFORE any code is copied or written based on upstream. Catches GPL/AGPL contamination of permissively-licensed projects (and vice-versa) early.
---
# License Pre-Check
Run this **before** copying, porting, adapting, or writing anything based on
upstream code. The goal: catch license incompatibilities before they
contaminate the package.
This skill exists because ComfyUI-Koolook v0.1.0 and v0.1.1 shipped under a
claimed MIT license while already incorporating GPL-3.0-derived code from
Radiance. The cleanup retroactively relicensed the entire package to GPL-3.0
(see `forks/THIRD_PARTY.md`). Future forks must not repeat this mistake.
## When to run this skill
- Before cloning any external repo for "we want to use their code" purposes.
- Before porting a node, function, or class from another project.
- Before adding a Python package as a runtime dependency that ships with the
package (not a normal pip install — anything that ends up in the
distribution tarball).
- Before merging a PR that adds files under `forks/` or imports new modules.
If the upstream is going into the sibling `../ComfyUI-Forks/` for **read-only
inspection** with no code copying, the skill is informational rather than
blocking — but still run it so the license is recorded in the manifest.
## Phase 1 — Identify what's coming in
Get from the user (or infer from the repo URL):
1. **Upstream repo URL.**
2. **What scope** is being incorporated:
- whole package (vendor),
- a subset of files (partial vendor),
- just patterns/interface (clean-room reimplementation),
- or runtime-only dependency.
3. **The intent** — fork & modify? mirror? simply call into it?
## Phase 2 — Read upstream's license
```bash
FORKS_ROOT="${KOLOOK_FORKS_DIR:-../ComfyUI-Forks}"
# If a clone already exists, read it. Otherwise do a shallow clone purely
# to read the LICENSE; remove afterwards if not keeping it.
# 2a. Find the LICENSE file at the repo root.
ls "$FORKS_ROOT/<clone>/LICENSE"*
# 2b. Read the first ~30 lines — that's enough to identify standard licenses.
head -30 "$FORKS_ROOT/<clone>/LICENSE"
# 2c. Cross-check the README and pyproject.toml — sometimes they disagree.
grep -i "license" "$FORKS_ROOT/<clone>/README.md" | head -5
grep -i "license" "$FORKS_ROOT/<clone>/pyproject.toml"
```
Record the **detected license SPDX identifier** (e.g. `GPL-3.0-or-later`,
`AGPL-3.0-only`, `MIT`, `Apache-2.0`, `BSD-3-Clause`, `MPL-2.0`, `LGPL-2.1`,
`UNLICENSED`/proprietary, or `unknown`). If `unknown`, **stop and ask the
user** — never assume permissive.
## Phase 3 — Compare to ComfyUI-Koolook's license
Read our current license:
```bash
head -3 LICENSE
grep -i "license" pyproject.toml README.md | head -10
```
Use this compatibility matrix (downstream = ComfyUI-Koolook; upstream = the
code being incorporated). "OK" means we can incorporate without changing our
license. "→ X" means we must relicense to X to incorporate.
| Upstream → \\ Our license ↓ | MIT | Apache-2.0 | LGPL-3.0 | GPL-3.0 | AGPL-3.0 |
|---|---|---|---|---|---|
| **MIT / BSD / ISC** | OK | OK | OK | OK | OK |
| **Apache-2.0** | OK ¹ | OK | OK | OK | OK |
| **MPL-2.0** | file-level OK ² | file-level OK ² | file-level OK ² | OK | OK |
| **LGPL-2.1 / LGPL-3.0** | dynamic-link only ³ | dynamic-link only ³ | OK | OK | OK |
| **GPL-2.0** | → GPL-2.0+ | → GPL-2.0+ | → GPL-2.0+ | → GPL ⁴ | → AGPL ⁴ |
| **GPL-3.0** | → GPL-3.0 | → GPL-3.0 | → GPL-3.0 | OK | → AGPL-3.0 |
| **AGPL-3.0** | → AGPL-3.0 | → AGPL-3.0 | → AGPL-3.0 | → AGPL-3.0 | OK |
| **Proprietary / no license** | ❌ STOP | ❌ STOP | ❌ STOP | ❌ STOP | ❌ STOP |
| **CC-BY-NC / non-commercial** | ❌ STOP for code ⁵ | ❌ STOP for code ⁵ | ❌ STOP for code ⁵ | ❌ STOP for code ⁵ | ❌ STOP for code ⁵ |
| **unknown / no LICENSE file** | ❌ STOP | ❌ STOP | ❌ STOP | ❌ STOP | ❌ STOP |
Footnotes:
1. Apache-2.0 → MIT: redistributing Apache code under MIT requires keeping
Apache's NOTICE file and per-file license headers; the *combined* work
stays MIT but the Apache portions remain Apache.
2. MPL-2.0 is file-level copyleft: you must keep the MPL on those files,
but the rest of the package can stay under your license.
3. LGPL allows linking from a non-LGPL host *only if* users can substitute
a modified LGPL library. For a Python package this usually means the
LGPL library is an external dep (pip-installable), not vendored.
4. GPL-2.0 and GPL-3.0 are not bidirectionally compatible without
`GPL-2.0-or-later`. Watch the version carefully.
5. Creative Commons licenses are designed for prose/media, not software.
CC-BY may be acceptable for asset files but never for code.
## Phase 4 — Report
Produce a single block to the user, blocking until they acknowledge:
```
LICENSE PRE-CHECK
─────────────────
Upstream: <repo URL> @ <commit/tag>
Upstream license: <SPDX>
Our license: <SPDX>
Scope of import: <whole | subset | clean-room | runtime-dep>
Compatibility: <OK | requires-relicense-to-X | BLOCKED>
If RELICENSE: explain what the user must change before proceeding.
If BLOCKED: stop. Recommend a clean-room alternative or a different
upstream with a compatible license.
Required attribution actions:
- Add an entry to forks/THIRD_PARTY.md
- Update forks/forks_manifest.yaml (license + license_verified_at)
- If GPL/LGPL: keep upstream LICENSE in any folder containing copied files
- If Apache: keep NOTICE file
- For modified files: prepend a header "Modified from <upstream>, <date>"
(GPL §5(a) requires this; Apache §4(b) requires a notice of changes)
```
## Phase 5 — Persist findings
Once compatibility is confirmed (or relicensing is decided), update:
1. `forks/forks_manifest.yaml` — `license:` and `license_verified_at:` fields
on the manifest entry.
2. `forks/THIRD_PARTY.md` — full attribution entry (see template at top of
that file).
3. If our license must change, that is its **own preceding chore PR** —
never bundle "relicense the whole pack" with "add a new fork", because
the legal change deserves a focused diff.
## Anti-patterns to refuse
- ❌ "I'll just copy the file and decide on the license later." Decide
first.
- ❌ "It's only one function" — copying still triggers the same license.
- ❌ "The README says MIT but the LICENSE file is GPL." The LICENSE file
controls (and you should report the discrepancy upstream).
- ❌ Adding a permissive shim that wraps GPL code while pretending the
shim is MIT. The combined work is still GPL.
- ❌ Treating `KOLOOK_FORKS_DIR` (read-only inspection) as if no license
check were needed. It's needed — to record the license in the manifest
even if no copying happens.
## Hand-off
After this skill completes successfully, hand off to
[`add-external-fork`](../add-external-fork/) for the actual clone +
register + wrapper steps. `add-external-fork` will refuse to run if the
manifest entry it would create has no `license_verified_at` field.
-184
View File
@@ -1,184 +0,0 @@
---
name: add-external-fork
description: Set up an external upstream repository as a pinned reference checkout under ../ComfyUI-Forks and register it in MAIN's fork tracking files. Use when adding a new third-party fork, cloning the Radiance (or other) baseline on a fresh machine, registering an external repo for upstream sync work, or asks about the forks/ workflow.
---
# Add External Fork
Encodes the ComfyUI-Koolook fork workflow: external upstream code is **never vendored into MAIN**. Instead, raw clones live in the sibling folder `../ComfyUI-Forks/`, MAIN tracks them via `forks/forks_manifest.yaml`, and any modified node code lives in MAIN under `forks/<package>/versions/<vX_Y_Z>/` with namespaced node IDs.
Use this skill whenever the user wants to:
- clone an external repo for upstream comparison/sync work,
- set up the documented baseline on a fresh machine,
- add a brand-new fork (with or without a wrapper module in MAIN),
- bump a fork to a new pinned version (creates a new `vX_Y_Z` folder).
## Conventions (do not deviate)
- **Forks root:** `../ComfyUI-Forks` (relative to MAIN). Overridable via env var `KOLOOK_FORKS_DIR`. Never clone third-party repos *inside* MAIN.
- **External folder names:**
- Pinned baseline → `<repo>-v<version>-koolook` (e.g. `radiance-v1.0.1-koolook`)
- Rolling upstream → `<repo>-main-upstream` (e.g. `radiance-main-upstream`)
- **Local version paths in MAIN:** `forks/<package>/versions/v<MAJOR>_<MINOR>_<PATCH>/`
- **Node ID namespace suffix:** `__koolook_v<MAJOR>_<MINOR>_<PATCH>` (must match the version folder).
- **Single source of truth:** `forks/forks_manifest.yaml`. Every external repo must have an entry there.
- **Never rename existing namespaced node IDs** that already appear in saved workflows. New versions get a new suffix.
## Phase 1 — Discover
Ask (or infer) before doing anything destructive:
1. **Repo URL** (e.g. `https://github.com/fxtdstudios/radiance.git`).
2. **Version label** (e.g. `1.0.1`). Used to name the folder and the namespace suffix.
3. **Pinned commit** (full hash). If unknown, offer to use the tip of the upstream default branch and record that hash.
4. **Source ref** (tag, branch, or descriptor — e.g. `comfyui (closest public baseline)`).
5. **Variants needed:**
- pinned baseline only?
- rolling upstream only?
- both?
6. **Wrapper in MAIN?** (yes if Koolook will modify nodes; no if it's reference-only.)
7. **Modified files** (paths that will live in MAIN under the new `versions/<vX_Y_Z>/`).
If the request is "set up the baseline on this machine" and a manifest entry already exists, **read the manifest** to get all of the above instead of asking — that's the whole point of `forks_manifest.yaml`.
## Phase 2 — External clones (outside MAIN)
```bash
FORKS_ROOT="${KOLOOK_FORKS_DIR:-../ComfyUI-Forks}"
mkdir -p "$FORKS_ROOT"
cd "$FORKS_ROOT"
```
### Pinned baseline
```bash
PIN_DIR="<repo>-v<version>-koolook"
git clone <source_repo> "$PIN_DIR"
cd "$PIN_DIR"
git checkout <pinned_commit>
git rev-parse HEAD # verify, must match pinned_commit
cd ..
```
### Rolling upstream (optional)
```bash
ROLL_DIR="<repo>-main-upstream"
git clone <source_repo> "$ROLL_DIR"
# leave on upstream default branch; do not check out a pin
```
If a clone already exists, do **not** re-clone. Instead `cd` in, fetch, and verify the commit/branch matches expectations. Report any drift.
## Phase 3 — Register in MAIN
### 3a. `forks/forks_manifest.yaml`
Append (or update) an entry. Mandatory fields:
```yaml
- id: "<package>_v<MAJOR>_<MINOR>_<PATCH>_baseline"
name: "<Human readable name>"
source_repo: "<URL>"
source_ref: "<tag/branch descriptor>"
pinned_commit: "<full sha>"
external_checkout:
relative_path_from_forks_root: "<repo>-v<version>-koolook"
upstream_tracking_path_from_forks_root: "<repo>-main-upstream"
default_branch: "<work branch name, optional>"
local_paths:
- "forks/<package>/versions/v<MAJOR>_<MINOR>_<PATCH>/__init__.py"
- "forks/<package>/versions/v<MAJOR>_<MINOR>_<PATCH>/UPSTREAM_PIN.yaml"
# plus every modified node source file
status: "modified" # or "reference_only"
sync_state: "local-modified-from-upstream"
license: "to_verify_at_source_ref"
notes: "<what was modified and why>"
```
Bump `updated_at` at the top of the file.
### 3b. `forks/THIRD_PARTY.md`
Add a new entry using the template at the top of that file. Keep it human-readable.
### 3c. Wrapper module in MAIN (only if `status: modified`)
Create the version folder:
```
forks/<package>/versions/v<MAJOR>_<MINOR>_<PATCH>/
__init__.py # imports node mappings + applies namespace suffix
UPSTREAM_PIN.yaml # mirrors manifest pin for one-file lookup
<copies of modified node source files>
```
`UPSTREAM_PIN.yaml` minimum:
```yaml
source_repo: "<URL>"
source_ref: "<descriptor>"
pinned_commit: "<full sha>"
external_checkout_relative_to_forks_root: "<repo>-v<version>-koolook"
upstream_tracking_relative_to_forks_root: "<repo>-main-upstream"
external_work_branch: "<branch>"
```
The version `__init__.py` must:
- import `NODE_CLASS_MAPPINGS` / `NODE_DISPLAY_NAME_MAPPINGS` from each modified node module,
- apply suffix `__koolook_v<MAJOR>_<MINOR>_<PATCH>` to every ID (and a display suffix like ` (Koolook v<version>)`),
- optionally register short-ID overrides (e.g. `k_easy_OCIO_v101`).
Then create/update the package entrypoint `forks/<package>/__init__.py` to merge all version mappings into a single `NODE_CLASS_MAPPINGS` / `NODE_DISPLAY_NAME_MAPPINGS`, and wire those into the **root `__init__.py`**.
### 3d. Documentation touchpoints
If the new fork changes user-visible behavior or adds/removes nodes:
- Add the new node IDs and categories to `README.md` (node table + categories list).
- Update `CHANGELOG.md` under `[Unreleased]`.
- Mention any new optional Python deps in the README "Compatibility" bullet.
## Phase 4 — Verify
Run from MAIN:
```bash
git status # MAIN should show only intended additions
python3 -c "import sys; sys.path.insert(0,'.'); import __init__ as m; print(sorted(m.NODE_CLASS_MAPPINGS))" # smoke test
ls "$FORKS_ROOT" # confirms external clones present
cd "$FORKS_ROOT/<repo>-v<version>-koolook" && git rev-parse HEAD # equals pinned_commit
```
If any of these fail, stop and report the discrepancy — do not paper over it.
## Phase 5 — Branch & commit
Per the repo's PR workflow, do MAIN-side changes on a feature branch, never on `main`:
```bash
git checkout -b feat/forks-add-<package>-v<MAJOR>_<MINOR>_<PATCH>
git add forks/ README.md CHANGELOG.md __init__.py
git commit -m "Add <package> v<version> fork wrapper and tracking."
```
External clones under `../ComfyUI-Forks/` are **not** committed to MAIN (they're outside the repo).
## Bumping an existing fork to a new pinned version
1. Phase 1: keep the existing entry; add a NEW entry with the new version.
2. Phase 2: clone a new pinned folder `<repo>-v<new_version>-koolook` (do not delete the old one — old workflows may need it for diff).
3. Phase 3: create a new `forks/<package>/versions/v<new>_<MAJOR>_<MINOR>_<PATCH>/` and a NEW namespace suffix. **Do not rename existing IDs.**
4. Update `forks_manifest.yaml`, `THIRD_PARTY.md`, README, CHANGELOG.
5. Verify both old and new namespaced IDs still resolve.
## Reference-only forks (no wrapper, no modifications)
Skip 3c entirely. Manifest entry uses `status: reference_only`, `local_paths: []`. External clone is still useful for inspection/docs.
## Anti-patterns
- ❌ Cloning third-party repos *inside* MAIN (e.g. `forks/<package>/upstream/`).
- ❌ Reusing an existing version folder for a different upstream commit.
- ❌ Renaming or removing namespace suffixes that already appear in saved workflows.
- ❌ Editing files inside `../ComfyUI-Forks/<repo>-v<version>-koolook/` and expecting MAIN to track them — that folder is reference-only.
- ❌ Updating `forks_manifest.yaml` without also updating the matching `UPSTREAM_PIN.yaml` (and vice-versa).
-37
View File
@@ -1,37 +0,0 @@
# ComfyUI-Koolook environment variables
#
# Copy this file to `.env` and fill in real paths for your machine.
# `.env` is gitignored — never commit real absolute paths to the public repo.
#
# Convention: KOLOOK_* prefix. Paths can be absolute or relative to MAIN.
# When unset, code/docs fall back to the documented portable default
# (when one exists).
# --- External forks root ----------------------------------------------------
# Where raw third-party clones live (outside MAIN). See forks/README.md.
# Default if unset: ../ComfyUI-Forks
KOLOOK_FORKS_DIR=
# --- Sibling projects -------------------------------------------------------
# Sibling projects are related repositories/folders we consult but do not
# fork or vendor. See README.md "Sibling Projects".
# ComfyUI knowledge database — sibling repository of ComfyUI references,
# workflow notes, and recipe research. Used by docs/agent skills as a
# read-only knowledge source.
# Default if unset: ../ComfyUI_knowledge___DB
KOLOOK_COMFYUI_KB_DIR=
# Personal knowledge database (Obsidian or similar) — entirely user-specific.
# Optional. Leave unset on shared/public clones; agents must treat the
# absence of this var as "no personal KB available".
# No default.
KOLOOK_PERSONAL_KB_DIR=
# --- Local dev sync ---------------------------------------------------------
# Path to a live ComfyUI custom_nodes folder where `scripts/sync_to_dev.py`
# copies runtime files for fast local iteration (skip the publish-and-update
# round-trip for one-line fixes). Leave unset to disable; the script errors
# out cleanly if invoked without it. Forward slashes work on Windows too.
# No default — entirely user-specific.
KOLOOK_COMFYUI_DEV_PATH=
-10
View File
@@ -1,10 +0,0 @@
{
"git.enabled": true,
"git.decorations.enabled": true,
"scm.diffDecorations": "all",
"scm.diffDecorationsGutterVisibility": "always",
"files.decorations.enabled": true,
"explorer.decorations.badges": true,
"explorer.decorations.colors": true
}
+7
View File
@@ -6,6 +6,13 @@ The format is inspired by Keep a Changelog and SemVer.
## [Unreleased]
## [0.2.1] - 2026-05-06
### Changed
- Cleaned the Registry release package by removing dev-only agent/editor
files and the local `scripts/sync_to_dev.py` helper. Runtime node code
is unchanged from v0.2.0.
## [0.2.0] - 2026-05-04
### Removed (BREAKING for any saved workflow using `Easy_Version`)
-68
View File
@@ -1,68 +0,0 @@
# ComfyUI-Koolook Agent Workflow
## Source-of-truth model
- MAIN repo: `ComfyUI-Koolook`
- External forks root (default): `../ComfyUI-Forks` (relative to MAIN)
- External third-party code must remain outside MAIN.
- Sibling projects (read-only references that live outside MAIN) are referenced via `KOLOOK_*` env vars only. Never hardcode absolute paths with usernames in committed files. Real paths live in `.env` (gitignored); the committed `.env.example` is the public template. See README "Sibling Projects" and `docs/reference/glossary.md`.
## Hard rules
- Do not vendor/copy full third-party repositories into MAIN.
- Keep MAIN limited to:
- custom Koolook nodes
- wrapper loaders under `forks/`
- fork tracking docs under `forks/`
- For third-party integrations, update:
- `forks/forks_manifest.yaml`
- `forks/THIRD_PARTY.md`
- `forks/README.md` (if workflow conventions change)
## Radiance fork policy (v2_3_3)
- Package entrypoint: `forks/radiance_koolook/__init__.py`
- Modified nodes live in MAIN and are GitHub-tracked:
- `forks/radiance_koolook/versions/v2_3_3/nodes_vae.py`
- External sibling checkout (`../ComfyUI-Forks/radiance-v2.3.3-koolook`) is raw reference only.
- Current baseline pin for raw comparison: `f262f47ddfda01ece154bf80c22769b1e4cef795` (the v2.3.3 release commit; the cleanest tag pointing at it is the typo'd `radinace2.3.3`, so we pin by SHA).
- Koolook-original node IDs (`Easy_hdr_VAE_encode`, `Easy_hdr_VAE_decode`) are exposed verbatim via the `SKIP_VERSION_SUFFIX` set in `versions/v2_3_3/__init__.py`. Future Koolook nodes in this fork can opt out the same way; future ports of upstream-named classes should keep the `__koolook_v2_3_3` suffix to avoid colliding with installed copies of upstream Radiance.
- `forks/forks_manifest.yaml` must include `source_ref` + `pinned_commit` + `license` + `license_verified_at`.
- The historical `v1_0_1` fork was removed in v0.1.5 — see `forks/THIRD_PARTY.md` for the rationale and recovery instructions.
## Change management
- When upgrading external forks (v2, v3, etc.), add a new wrapper/version namespace.
- Never rename existing namespaced node IDs that already appear in saved workflows.
## `dev-sync` — copy runtime files into a live ComfyUI install
For fast iteration on a fix that doesn't deserve its own version bump,
copy runtime files straight into a live ComfyUI custom_nodes folder
instead of cutting a release.
- Set `KOLOOK_COMFYUI_DEV_PATH` in `.env` (see `.env.example`). The path
must point at the maintainer's `custom_nodes/<koolook-folder>/`. It is
intentionally kept out of the committed tree.
- Run `python scripts/sync_to_dev.py` (or `--dry-run` to preview).
- Restart ComfyUI to load the new code.
**Trigger phrase: `dev-sync`** (or any clear synonym like "copy those
files", "sync dev", "push to dev"). When the maintainer says it during
a session, the agent runs `scripts/sync_to_dev.py` and reports what was
copied. The script errors out cleanly when the env var is unset; never
guess a path.
This is a development convenience only — anything worth shipping still
goes through the normal PR + release flow described below.
## Releasing
- The canonical release procedure is `docs/maintainers/releasing.md`. Follow it for every
`vX.Y.Z` cut — do not invent a one-off flow.
- The per-release tickbox mirror is `.github/ISSUE_TEMPLATE/release_checklist.md`.
Open one as a tracking issue when starting a release.
- Always validate the Comfy Registry publish against the PR branch
(`gh workflow run publish.yml --ref release/vX.Y.Z-prep`) before merging.
A `Failed to validate token` error is almost always a `[tool.comfy] PublisherId`
mismatch, not a token problem.
+2 -2
View File
@@ -2,7 +2,7 @@
This repository provides custom nodes for ComfyUI tailored for VFX and AI image/video generation workflows.
For change history see [`CHANGELOG.md`](CHANGELOG.md). For workflow conventions and naming see [`CLAUDE.md`](CLAUDE.md) and the [glossary](docs/reference/glossary.md). Full project documentation lives under [`docs/`](docs/).
For change history see [`CHANGELOG.md`](CHANGELOG.md). For workflow conventions and naming see the [glossary](docs/reference/glossary.md). Full project documentation lives under [`docs/`](docs/).
### Koolook nodes (root package)
@@ -265,4 +265,4 @@ are tracked in [`forks/THIRD_PARTY.md`](forks/THIRD_PARTY.md) and
> (or a compatible license). If you need a non-copyleft license for any
> piece of this code, contact the maintainers — some Koolook-original
> nodes (those with no upstream Radiance lineage) may be available under
> a more permissive license on request.
> a more permissive license on request.
-1
View File
@@ -15,4 +15,3 @@ Three audience buckets — pick where to look based on what you're trying to do.
| [`../README.md`](../README.md) | GitHub repo home + Comfy Registry pulls description from here |
| [`../LICENSE`](../LICENSE) | `pyproject.toml` references it; GitHub recognizes the license badge from this path only |
| [`../CHANGELOG.md`](../CHANGELOG.md) | Changelog parsers and release tooling expect it at root |
| [`../CLAUDE.md`](../CLAUDE.md) | Claude Code reads project-level agent instructions from `<repo>/CLAUDE.md` |
+2 -10
View File
@@ -3,9 +3,8 @@
Project-internal procedures. If you're cutting a release, forking a node,
hitting the Comfy Registry API, or debugging CI — read these first.
These are docs for **humans** doing the work. The corresponding **agent**
workflows for Claude Code live in [`../../.claude/skills/`](../../.claude/skills/)
and should be kept in sync with these prose docs.
These are docs for **humans** doing the work. Keep any local agent workflows
in sync with these prose docs.
## Contents
@@ -14,10 +13,3 @@ and should be kept in sync with these prose docs.
| [`releasing.md`](releasing.md) | Canonical step-by-step release procedure: branch → PR → publish-validate → squash-merge → tag → GitHub Release. Anti-patterns to avoid. The per-release tickbox mirror is [`.github/ISSUE_TEMPLATE/release_checklist.md`](../../.github/ISSUE_TEMPLATE/release_checklist.md). |
| [`registry-api.md`](registry-api.md) | The Comfy Registry's undocumented version-management endpoints (deprecate, delete, query) reverse-engineered while cleaning up v0.1.0–0.1.5. Includes ready-to-paste curl commands and an optional GitHub Actions workflow YAML for codified version management. |
| [`node-versioning.md`](node-versioning.md) | Hard-won rules for changing `INPUT_TYPES` / `RETURN_TYPES` / class names without breaking saved user workflows. The five rules + the suffix-version pattern (`MyNode` → `MyNodeV2`) + the alias-then-deprecate migration path. |
## Companion agent skills
| Skill (in `.claude/skills/`) | Mirrors this doc |
|---|---|
| `license-pre-check` | Runs *before* any third-party fork; refuses to proceed on incompatible licenses. The principles also apply when a human is doing it manually. |
| `add-external-fork` | The `forks/` workflow — clone outside MAIN, register in `forks_manifest.yaml`, namespace the IDs. Phase 0 calls `license-pre-check`. |
+1 -3
View File
@@ -103,6 +103,4 @@ below — GPL-3.0 §5(c) requires the whole work to be GPL-3.0.
- Keep only wrappers/manifests in MAIN; do not vendor large third-party trees here.
- Keep modified node source files in MAIN when you want full GitHub tracking
and one-repo commits.
- **Run [`license-pre-check`](../.claude/skills/license-pre-check/) before
adding any new third-party fork** — it catches license incompatibilities
*before* you start copying code.
- Run a license compatibility check before adding any new third-party fork.
+2 -1
View File
@@ -4,7 +4,8 @@ Each `versions/vX_Y_Z/` subpackage owns a namespaced slice of nodes.
This entrypoint just merges all version mappings into a single dict
for the root loader.
Adding a new version: see `.claude/skills/add-external-fork/SKILL.md`.
Adding a new version: register it in `forks_manifest.yaml`, namespace the
node IDs, and update the attribution docs.
History:
- v1_0_1 (24 wrapped Radiance v1.0 classes + 2 modified) was removed in
+1 -2
View File
@@ -1,7 +1,7 @@
[project]
name = "koolook"
description = "This repository provides custom nodes for ComfyUI tailored for VFX and AI image/video generation workflows"
version = "0.2.0"
version = "0.2.1"
license = {file = "LICENSE"}
# classifiers = [
# # For OS-independent nodes (works on all operating systems)
@@ -39,4 +39,3 @@ extend-exclude = [".venv", "forks", "upscaler_FIX", "nuke_CAM_exporter"]
[tool.ruff.lint.per-file-ignores]
"k_easy_resize.py" = ["F841"]
-137
View File
@@ -1,137 +0,0 @@
#!/usr/bin/env python3
"""
Copy runtime-relevant Koolook files into a live ComfyUI custom_nodes
folder so a fix can be tested without a tag-and-publish round-trip.
The target path is read from the KOLOOK_COMFYUI_DEV_PATH environment
variable (loaded from `.env` at the repo root if present). The variable
is intentionally kept out of the committed tree — see `.env.example`.
Usage:
python scripts/sync_to_dev.py # copy all runtime files
python scripts/sync_to_dev.py --dry-run # show what would copy
Exit codes:
0 success
2 KOLOOK_COMFYUI_DEV_PATH unset or target missing
This script never reaches outside the repo, never deletes anything in
the source, and only touches paths under the configured target. It does
overwrite files in the target — that's the point.
"""
from __future__ import annotations
import argparse
import os
import shutil
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
# Files / dirs ComfyUI actually loads at runtime. Anything outside this
# list (CI, docs, .claude/, .github/, .cursor/, CHANGELOG, LICENSE,
# pyproject.toml, README, fork manifest YAML, etc.) does not affect what
# ComfyUI executes and is intentionally skipped.
RUNTIME_PATHS: tuple[str, ...] = (
"__init__.py",
"config.json",
"k_ai_pipeline.py",
"k_easy_image_batch.py",
"k_easy_resize.py",
"k_easy_track.py",
"k_easy_version.py",
"k_easy_wan22_prompt.py",
"forks",
"web",
)
# When copying directories, exclude these subpaths — they are dev-only
# metadata that ComfyUI doesn't need and which can churn unnecessarily.
DIR_EXCLUDES: tuple[str, ...] = (
"__pycache__",
"UPSTREAM_PIN.yaml",
"THIRD_PARTY.md",
"forks_manifest.yaml",
"README.md",
)
def load_dotenv(env_path: Path) -> None:
"""Minimal `.env` loader. No dependency on python-dotenv."""
if not env_path.exists():
return
for line in env_path.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, _, value = line.partition("=")
# Don't overwrite anything already in the environment.
os.environ.setdefault(key.strip(), value.strip().strip('"').strip("'"))
def _ignore(_dir: str, names: list[str]) -> list[str]:
return [n for n in names if n in DIR_EXCLUDES]
def sync(target: Path, dry_run: bool) -> int:
copied = 0
for rel in RUNTIME_PATHS:
src = REPO_ROOT / rel
if not src.exists():
continue
dst = target / rel
if dry_run:
print(f"would copy: {rel}")
copied += 1
continue
if src.is_dir():
if dst.exists():
shutil.rmtree(dst)
shutil.copytree(src, dst, ignore=_ignore)
else:
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst)
print(f"copied: {rel}")
copied += 1
return copied
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--dry-run",
action="store_true",
help="Print what would be copied without touching the target.",
)
args = parser.parse_args()
load_dotenv(REPO_ROOT / ".env")
target_str = os.environ.get("KOLOOK_COMFYUI_DEV_PATH")
if not target_str:
print(
"KOLOOK_COMFYUI_DEV_PATH not set. Add it to .env "
"(see .env.example).",
file=sys.stderr,
)
return 2
target = Path(target_str).expanduser()
if not target.exists():
print(f"target does not exist: {target}", file=sys.stderr)
return 2
if not target.is_dir():
print(f"target is not a directory: {target}", file=sys.stderr)
return 2
n = sync(target, dry_run=args.dry_run)
verb = "would sync" if args.dry_run else "synced"
print(f"\n{verb} {n} entries -> {target}")
if not args.dry_run:
print("restart ComfyUI to pick up changes.")
return 0
if __name__ == "__main__":
sys.exit(main())