Commit Graph
30 Commits
Author SHA1 Message Date
040b30733d feat(matte): first-party mask-guided one-step video matting nodes (#269)
* feat(matte): first-party mask-guided one-step video matting nodes

Adds matte/ — an independent implementation of the published VideoMaMa
one-step SVD method (matte/pipeline.py) plus Koolook's temporal windowing,
subject-focused crop/stitch, resolution control (/64, shortest-side) and
auto OOM resolution-backoff. Nodes: KoolookMatteLoader, KoolookMatteSampler,
KoolookMatteFocusCrop, KoolookMatteFocusStitch.

Registered via the existing guarded _merge_node_group("Koolook Matte",
".matte"), so a missing diffusers disables only these nodes. diffusers is
already pulled in by the radiance/whatdreamscost forks, so no new dependency.

Loads (never bundles) the VideoMaMa UNet (CC-BY-NC) + SVD VAE at runtime;
matte/NOTICE records the model licenses and user responsibility.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(dev-sync): include matte/ in RUNTIME_PATHS

So `sync_to_dev` copies the new matte node package into the live ComfyUI
install alongside the rest of the koolook pack.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(matte): raw cond latents; fp16 default; preserve checkpoints on dev-sync

pipeline.py: _encode_latents must NOT divide by vae scaling_factor. The
VideoMaMa UNet is trained on raw VAE latents (matching okdalto's
VideoInferencePipeline, which multiplies by scaling_factor then divides it
back out -> net x1). Dividing over-scaled the conditioning ~5.5x and produced
a systematically blurry matte on every frame. Verified 5/5 vs the desktop /
vanilla reference on identical single-frame inputs.

nodes.py: harden the loader precision fallback so fp16 is the true default -
only an explicit "bf16" opts out; a stale "auto" widget now resolves to fp16
instead of bf16.

sync_to_dev.py: the rmtree+copytree mirror deleted matte/checkpoints/ (the
gitignored ~10GB SVD+VideoMaMa weights) on every matte sync, forcing a
re-download. Add PRESERVE_IN_DEST + selective _clean_dest so runtime-
downloaded model data survives a sync.

docs: add docs/maintainers/matte-pipeline.md (latent-scaling invariant,
black-output causes, fidelity levers, single-frame + vanilla-oracle debug
loop, checkpoint preservation).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(matte): address PR #269 review

- license: align matte to the repo's GPL-3.0 (was self-contradictory: claimed
  "MIT licensed - see LICENSE" while LICENSE is GPL-3.0). pipeline.py header,
  NOTICE, and the maintainer doc updated. NOTICE still credits VideoMaMa
  (CC BY-NC) + SVD (Stability Community License).
- nodes.py _ensure_2d_mask: squeeze first, then handle [H,W,C]/[C,H,W]
  explicitly and RAISE on ambiguous shapes -- previously [H,W,3] silently
  became [W,3] (wrong geometry).
- nodes.py OOM backoff: catch RuntimeError (OutOfMemoryError subclasses it, but
  cuBLAS/cuDNN/older paths raise plain "RuntimeError: CUDA out of memory"); the
  existing message guard still filters non-OOM errors.
- nodes.py: warn when the guide mask is empty instead of silently falling back
  to full-frame.
- sync_to_dev.py: PRESERVE_IN_DEST is now an exact relative path
  ("matte/checkpoints"), not a bare name matched at any depth; handle symlinks
  before is_dir() in _clean_dest so a symlinked dir isn't recursed/rmtree'd.
- CHANGELOG: add the Koolook Matte nodes under [Unreleased] with the
  non-commercial model-license caveat.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(matte): address PR #269 re-review

- sync_to_dev.py [BLOCKING]: a top-level symlinked dest (e.g. target/matte -> X)
  was passed straight into _clean_dest()/copytree(), which follow the link and
  can mutate files outside the target. Now unlink a symlinked dest and own the
  path as a real dir (checked before exists(), which follows symlinks). Verified
  with a repro: the symlink target's file survives.
- nodes.py: force float32 on a CPU fallback (CUDA unavailable). Half precision
  is unreliable on CPU; fp16 kernels would error. Warn that CPU is very slow.
- docs: correct the preserved-path guidance to the target-relative
  "matte/checkpoints" (was a bare "checkpoints" name); reword "near-verbatim
  reimplementation" -> "independent implementation targeting behavioural parity"
  to match the NOTICE/pipeline framing.
- nodes.py: also warn on a degenerate (<8px) guide-mask region before the
  full-frame fallback (was silent).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(matte): address PR #269 re-review (CI red + FocusCrop frame check)

- nodes.py: KoolookMatteFocusCrop now validates images vs coarse_mask frame
  counts (raises like KoolookMatteSampler.run_inference). A mismatch previously
  made cropped_images/cropped_mask diverge and silently drop/misalign frames at
  FocusStitch.
- pipeline.py: split "vae.to('cpu'); _clear_cache(...)" onto two lines (Ruff
  E702 was failing Lint & Smoke).
- constraints-test.txt: bump pillow 12.2.0 -> 12.3.0 (pip-audit CVE, fixed in
  12.3.0). Pillow is a leaf dep so the closure is unaffected; CI re-audits.
- README: note the Koolook Matte nodes need diffusers (already via the LTX /
  Radiance forks) and huggingface_hub for runtime weight downloads.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: AI Machine <ai.machine@x.baconcph.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 17:03:12 +02:00
malkuthro b6b95d8a85 docs: add Ko-fi funding link (#260) 2026-06-23 00:29:00 +02:00
malkuthro ae7abba73b docs: refresh shipped help and tooltips (#249)
* docs: refresh shipped help and tooltips

* docs: add snapshot transfer guide section

* docs: refresh guide screenshots
2026-06-19 01:01:30 +02:00
malkuthro 8c8546c17c Add queue-driven loop status controller (#205)
* Add queue-driven loop status node

* Document ComfyUI server API testing

* Harden loop queue controller

* Guard loop controller HTTP requests
2026-06-03 12:34:15 +02:00
malkuthro 67e9d55e98 docs(nodes): add user guides and tooltips (#200)
* docs(nodes): add user guides and tooltips

* chore: clean up node preflight nits
2026-06-02 20:42:56 +02:00
8058e17456 fix(snapshot): paired drift-corruption fix — duplicate-install guard + boot-time mismatch (#161, #162) (#186)
* fix(snapshot): prevent drift corruption from duplicate installs + boot-time mismatch (#161, #162)

Closes #162 and #161 as the paired fix the issues describe — both touch
the same data-loss surface and verify against the same dev-sync rig.

installs at import time, log critical, register nothing in the
alphabetical loser; client-side `window` sentinel as belt-and-suspenders;
align .env.example / dev-iteration-loop / sync_to_dev / README at the
Registry-derived `koolook/` path.

compare against live /userdata + picks, set a drift flag on mismatch;
gate periodic + pre-load autosave routing to `_unsaved_autosave/` while
drifted; promote status pill to "drifted" precedence over "saved" with a
recovery tooltip; auto-clear on the next markStateSaved (Save / Load).

26 new tests (14 install guard, 4 sidebar sentinel, 8 boot drift) —
316 total passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(snapshot): apply review fixes — canonical fingerprint + early loser exit + drift timestamp

Review-driven follow-ups on PR #186:

1. **Symmetrize file-side fingerprint (MEDIUM).** `detectBootDrift`
   now uses a new `_canonicalStateFingerprint()` that normalizes the
   workflows tree through `normalizeWorkflowsStore` AND deep-sorts keys
   via `sortJsonValue`. Without this, hand-edited / cross-machine /
   pre-v0.3 files would false-positive as drifted on first boot
   (e.g. `archived: "false"` string vs `false` bool, missing
   `directories: {}`, key insertion-order asymmetry from the
   `{...wf, archived, module, tags}` spread). `_computeFingerprint`
   stays unchanged so the localStorage save baseline contract holds
   for existing users. New regression test verifies a shape-only diff
   does NOT trigger drift.

2. **Gate fork imports on `_is_winning_install` (LOW).** Non-winning
   duplicate installs now short-circuit before the heavy torch / PIL /
   diffusers / aiohttp imports, exiting in ~5 LoC instead of paying
   full import cost just to discard the mappings.

3. **Drift timestamp uses `driftDetectedAt`, not stale
   `lastNamedSaveAt` (LOW).** The localStorage save baseline could be
   from a prior session whose live state was already corrupt —
   surfacing it as "Last named save" in the drift tooltip would
   mislead. Replaced with the session-noticed-at timestamp from
   `_bootDriftDiagnostics`.

352 tests passing (316 prior + 26 from PR #186 + 1 new normalize-
symmetry case).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(install-guard): fail safe on unreadable / non-UTF-8 siblings (#162)

Re-review follow-up. The import-time duplicate-install scan could crash
the entire plugin load (fail-silent — the alphabetical winner vanished
too, not just the loser) on two unguarded paths:

- detect_duplicate_koolook_installs: the per-entry is_dir()/is_file()
  over custom_nodes/ siblings was unguarded, so a non-traversable
  sibling (restrictive perms, broken mount, a special dir) raised
  PermissionError up into __init__.py. No duplicate even required.
  Now caught per-entry and skipped.
- read_pyproject_version: read_text(encoding="utf-8") raises
  UnicodeDecodeError (a ValueError, NOT OSError) on a non-UTF-8 /
  binary pyproject.toml, escaping the `except OSError`. Now degrades
  to "?" via `except (OSError, ValueError)`.
- __init__.py: wrapped the guard call site as a final backstop — any
  unforeseen guard failure now degrades to register-normally rather
  than aborting the import.

Both paths reproduced before the fix; the first surfaced while running
the suite from a /tmp checkout whose parent held a root-owned dir.

3 regression tests added (non-traversable sibling skipped; non-UTF-8
pyproject -> "?"; report survives a non-UTF-8 sibling). Full suite:
452 passed (449 + 3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: kflame99 <261674183+kflame99@users.noreply.github.com>
2026-06-02 18:44:57 +02:00
malkuthroandClaude Opus 4.7 4739dd4203 feat: Easy_Utility, Easy_LoadVideo, and preview fixes (#184)
* feat(nodes): add Easy_Utility — INT → padded STRING dispatcher

First mode `int_to_padded_string`: takes an INT widget (with up/down
arrows) and emits a zero-padded STRING (default `001`, no `v` prefix).
The downstream `koolook_versioning.resolve_version_token` prepends `v`
and re-pads, so wiring this into `EasyAIPipeline.version` /
`Easy_VideoCombine.version` yields the standard `vNNN` token at execution.

Designed for extension: the `mode` widget shipped from day one so adding
further conversions (string→int, formatting variants, etc.) doesn't
rewire saved workflows.

Note: the previously-attempted JS preview-resolver refactor that aimed
to fix the "preview shows stale version" bug was reverted in this
worktree before commit — it didn't actually fix the bug (the real cause
is the JS resolver not descending into ComfyUI subgraphs) and it broke
shot_name resolution in the process. The preview-resolver work is NOT
in this commit; only the Python node + tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(nodes): guard version widget against pysssss .replace crash

PR #180 added a STRING `version` widget to EasyAIPipeline and
Easy_VideoCombine. Three workflow states leave widget.value undefined
or non-string when graphToPrompt iterates widgets:

- Pre-#180 workflows replay an INT (e.g. `1`) into the new STRING slot.
- Widget-to-input conversion voids the value in newer LiteGraph.
- Easy_VideoCombine's dict-based widgets_values omits the new key
  entirely on workflows saved before #180.

With pysssss/ComfyUI-Custom-Scripts installed, presetText.js patches
every STRING TextWidget.serializeValue to run callbacks that do
`value.replace(...)` for `{variable}` substitution. Any of the states
above crashes graphToPrompt and turns Run into a no-op for the whole
workflow ("Cannot read properties of undefined (reading 'replace')").

Fix: trap `widget.value` reads/writes on the version widget via
`Object.defineProperty` so the property is always coerced to a string
regardless of caller. `configurable: true` so downstream code can
still override the descriptor if it needs to.

Tests: 231 passing; both JS files parse OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ai-pipeline): resolve subgraph version preview

* feat(video): add path-aware load video node

* fix(ai-pipeline): preview connected text names

* fix(pr184): address review cleanup

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 15:59:27 +02:00
malkuthro 7d46d1cdf2 Release v0.3.7 (#175)
* Release v0.3.7: support docs and fixes

* docs: align bug report privacy guidance
2026-05-23 10:23:04 +02:00
malkuthroandClaude Opus 4.7 ff79b0f418 feat(video): add Easy_VideoCombine (#154)
* feat(video): add Easy_VideoCombine with absolute-path support

Adds a Koolook subclass of VHS VideoCombine that bypasses ComfyUI's
output-directory sandbox when filename_prefix is an absolute path —
the VFX-pipeline missing piece for writing renders into a project
tree (e.g. E:/projects/shot01/v003) instead of ComfyUI/output/.

Implementation:
- k_video_combine.py: ~60 LoC subclass + a pure _resolve_abs_target
  helper. Scoped-patches folder_paths.get_save_image_path for the
  duration of one combine_video() call so upstream's encoder, audio
  mux, batch manager, and progress bar run unchanged. No VHS code
  copied. Self-skips registration when VHS isn't importable (clean
  one-line stderr notice).
- Discriminator: os.path.isabs(filename_prefix). No new input pin;
  pattern borrowed from spacepxl/ComfyUI-HQ-Image-Save's SaveEXR.
- Optional create_path_if_missing BOOLEAN (default False) so typos
  surface as FileNotFoundError instead of spawning stray dirs.

License audit (2026-05-16):
- VHS upstream: GPL-3.0 (verified via raw LICENSE fetch).
- HQ-Image-Save pattern source: MIT, copyright 2023 spacepxl.
- Koolook: already GPL-3.0; both upstreams are compatible.
- No source code from either upstream is incorporated.

Verification: 18 pytest cases green (12 existing + 6 new covering
relative passthrough, absolute resolution, create-on/off branches,
trailing-separator normalization, and empty-basename rejection).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(starter-preset): pre-favourite Easy_VideoCombine

Adds the new node to the shipped starter_preset.json picks so fresh
installs surface it in the Kforge Labs sidebar's Nodes section without
the user having to discover it via Comfy's stock search first. Pairs
naturally with the existing LoadEXR / SaveEXRFrames picks from
HQ-Image-Save.

Existing installs with non-empty picks are unaffected (the seeder
skips them by design); they can either Load -> "starter" in the
Snapshot dialog or hit "+" once in the Nodes section to pull it in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(dev-sync): include k_video_combine.py in RUNTIME_PATHS

Without this entry the new Easy_VideoCombine module is never copied
into the dev ComfyUI install, so the node fails to register on
restart with a silent ImportError. Caught when the maintainer
restarted ComfyUI and couldn't find the node in the search palette.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(starter-preset): include all Koolook nodes in default picks

Fresh installs should land on a populated Nodes (favorites) panel
that immediately surfaces what Koolook provides — otherwise new
users see only third-party picks and have no entry point into the
Koolook-native workflow. Adds the 8 currently-registered Koolook
node IDs to the shipped starter preset alongside the existing
third-party essentials:

  EasyAIPipeline, EasyResize_Koolook, EasyWan22Prompt,
  Easy_Pattern, Easy_VideoCombine, Easy_hdr_VAE_decode,
  Easy_hdr_VAE_encode, KoolookLoadCameraPosesAbsolute,
  easy_ImageBatch

Also adds Easy_VideoCombine to the README's Included Nodes table.

Existing installs with non-empty picks are unaffected by the seeder
(by design). To pull the Koolook defaults into an existing install,
Quick Save first, then Snapshot -> Load -> "starter".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(video): reach VHS_VideoCombine via nodes.NODE_CLASS_MAPPINGS

The previous `from videohelpersuite.nodes import VideoCombine` fails
inside ComfyUI's loader context because VHS uses relative imports
throughout (`from .logger ...`, `from .utils ...`) that only resolve
when VHS is loaded through ComfyUI's importlib spec — not through a
plain absolute import path. The error surfaced as

    No module named 'utils.install_util'; 'utils' is not a package

at Koolook load time, which caused the node to self-skip with an
empty NODE_CLASS_MAPPINGS — invisible in ComfyUI's search palette.

Fix: look up VHS_VideoCombine through `nodes.NODE_CLASS_MAPPINGS`,
which is the documented cross-pack interface. ComfyUI's loader
(custom_nodes/.../__init__.py exec_module → merge into global) runs
to completion for each pack before moving to the next, and VHS sorts
before Koolook alphabetically in every layout we've seen, so by the
time Koolook's __init__.py runs the global registry already has
VHS_VideoCombine in it.

Verified against ComfyUI's nodes.py load_custom_node() at
load_custom_node() lines 2196 (exec_module) and 2225-2228 (merge),
which guarantee this ordering.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(video): add output_directory input for split path/name editing

Overloading filename_prefix for absolute paths means losing the
"just type a name" affordance — once you put the path there, there's
nowhere to specify just the file root. Across many renders into the
same project tree this becomes tedious: every iteration retypes the
whole path.

Adds an optional `output_directory` STRING input. When set:
  - filename_prefix is treated as just the filename root; any path
    components are stripped (so accidental typos like "sub/clip"
    don't double-up under the directory).
  - Absolute output_directory writes directly to that location.
  - Relative output_directory joins under ComfyUI's output/.

When output_directory is empty, the original overloaded
filename_prefix behavior is preserved unchanged (back-compat for
the one-field flow).

Implementation:
- New pure helper `_compose_prefix(filename_prefix, output_directory)`
  combines the two fields into one effective prefix. The existing
  isabs discrimination then handles sandboxed vs absolute writes
  uniformly downstream.
- 6 new tests cover all combinations: empty/abs/relative directory,
  path stripping from filename_prefix, trailing-separator trim,
  empty-name fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(video): coerce frontend 'undefined' STRING values to empty

The ComfyUI frontend serializes a STRING widget with empty default
as the literal string "undefined" when left untouched (a known
long-running quirk). Without defensive normalization, an untouched
output_directory was treated as a real directory name and prepended
to the user's path:

  filename_prefix = "E:/renders/clip_v003" (typed by user)
  output_directory = "undefined" (frontend default, not typed)

  _compose_prefix(...) -> "undefined/clip_v003"      (relative)
  _resolve_abs_target -> None (not absolute)
  super().combine_video -> writes to <output>/undefined/clip_v003_*

The QuickTime ended up at <ComfyUI>/output/undefined/<name>.mov
with a spurious `undefined/` subfolder, instead of at the absolute
path the user actually specified.

Fix: a `_normalize_text_input()` helper coerces the literal strings
"undefined" / "null" / "None" (case-insensitive, post-strip) to "".
Applied to both filename_prefix and output_directory at the top of
combine_video() before any path composition. 4 new tests cover the
sentinels and a regression test for the exact path-composition
behavior that produced the bug.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(video-fe): wire format-specific widgets for Easy_VideoCombine

VHS's frontend extension (web/js/VHS.core.js:2030) gates its
format-widget machinery on `nodeData?.name == "VHS_VideoCombine"` —
strict-equality on the registered node ID. Our subclass uses a
different ID (`Easy_VideoCombine`), so none of VHS's per-format
widget rendering ran. The user saw:

    [VideoHelperSuite] - WARNING - Missing input for p has been set to hq

on every execution (profile defaulting to "hq" for ProRes), and
had no way to pick anything other than the default — because the
profile dropdown was never rendered.

Fix: a minimal frontend extension at web/easy_video_combine.js
(~80 LoC) that replicates `addFormatWidgets` for our node name.
Hooks the format dropdown's callback to add/remove per-format
widgets the same way upstream does. Self-contained — does not
import from VHS's module (their helpers aren't exported as ES
imports).

Verifies via the actual ComfyUI install after dev-sync; static
preview servers can't exercise it (depends on LiteGraph's
registered_node_types at runtime).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(video): strip 'undefined' from anywhere + one-shot debug log

The previous normalization only caught the EXACT literal "undefined"
/ "null" / "None" at field-level. Adds two stronger defenses for the
case where a sentinel still slips through:

1. _normalize_text_input now also strips surrounding quotes (paste-
   from-Explorer artifact) and handles embedded newlines by taking
   the first non-empty non-sentinel line (defends against multi-line
   Text Multiline inputs with trailing blank or junk lines).
2. New _strip_sentinel_components helper drops any path component
   that is exactly a sentinel string from the composed effective_
   prefix — belt-and-suspenders for any path that somehow carries
   `\undefined\` as a literal segment by the time it reaches us.

Also adds a one-shot print() of fp_raw, od_raw, normalized values,
and effective_prefix at the top of combine_video. The user is
seeing an undefined/ folder under their custom path despite the
field-level normalization, and pure code tracing doesn't reproduce
it — the log will surface what kwargs actually contains at run
time so we can fix the real cause if defensive stripping doesn't
already handle it. To be removed in a follow-up once root cause
is known.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(video): trim node docstring + tooltips, remove debug print

- Class docstring collapsed from ~20 lines to a single sentence (the
  frontend was showing it as the node description on right-click,
  cluttering the UI).
- Widget tooltips trimmed to one short sentence each — same intent,
  no walls of text.
- Debug print() added in 943be67 removed (defensive strip handled
  the undefined/ bug; no further diagnosis needed).
- Local fp_raw / od_raw variables (only used by the debug print)
  collapsed back into direct call sites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(video): suppress metadata PNG + silent intermediate by default

Upstream VHS writes 3 files per render when audio is connected:
  - <name>_NNNNN.png      (first-frame sidecar with workflow metadata)
  - <name>_NNNNN.mov      (silent intermediate)
  - <name>_NNNNN-audio.mov (final audio-muxed video)

Both extras are controlled by hidden VHS_MetadataImage and
VHS_KeepIntermediate flags in extra_pnginfo['workflow']['extra'],
both default-on upstream. Result: a single 500MB render lands as
three files (one needed, two clutter), nearly 2x the disk footprint
and a confusing folder.

Adds two optional BOOLEAN inputs (both default False on Koolook):
  - save_metadata_png
  - keep_silent_intermediate

combine_video injects them into extra_pnginfo before delegating to
super(), so the existing upstream flags do the actual work — no
post-hoc file deletion, no fork divergence from upstream's encoder
path. The extra_pnginfo dict is copied (not mutated in place) so
other nodes in the workflow that reference the same dict are
unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* diag(video): log frame-count + audio length, restore PNG default-on

Two changes to investigate a doubled-length output report:

1. Default save_metadata_png back to True (was False since 946e170).
   The PNG sidecar carries the embedded workflow JSON — it's the
   only audit trail when a render comes out wrong. Removing it by
   default left no way to diagnose retroactively. Users who don't
   want the sidecar can still toggle it off explicitly; ones who do
   want auditability (most VFX pipelines) get it automatically.

2. One-shot diagnostic print() at the top of combine_video logging:
   - input image batch size + shape
   - audio sample count + sample rate -> seconds
   - frame_rate -> expected video seconds
   - pingpong + loop_count

This pins down whether a doubled-length output is the image stream
arriving already-doubled (workflow issue: ImageConcatMulti in batch
mode, an upstream pingpong, etc.) vs combine_video itself doing
something with the frames. To be removed in a follow-up once the
current report is diagnosed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(video): restore Easy_VideoCombine widgets by name

* feat(video): polish Easy_VideoCombine review workflow

* test(video): fix Easy_VideoCombine pytest coverage

* docs: require repo-local Python venv

* fix(video): handle existing silent mux intermediates

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 14:53:18 +02:00
malkuthroandClaude Opus 4.7 9dab85c695 feat(easy_pattern): add test-pattern node + auto-restart dev-sync (#135)
* feat(easy_pattern): add test-pattern node + auto-restart dev-sync

Adds an `Easy_Pattern` node (Koolook/Testing) for solid-color frame
batches with optional per-frame index overlays — verifies sequence
merging, frame insertion, batch indexing, and video-pipeline frame
order at a glance. Color inputs use the same
`White/Black/Gray/Custom` dropdown idiom `EasyResize_Koolook` already
exposes for pad/panel colors, so "Gray" means the same 50% sRGB across
nodes.

`scripts/sync_to_dev.py` now restarts the live ComfyUI server after a
successful sync (via ComfyUI-Manager's `/manager/reboot`). Default-on
because dev-sync is only ever invoked to see new code, and Python
custom-node files load once at server start — `--no-restart` is the
escape hatch. The `RUNTIME_PATHS` manifest also picks up
`k_easy_pattern.py` so adding a new top-level node doesn't silently
break the pack at import time on the next sync.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(sync-dev): restrict restart URL to http(s) for Bandit B310

`urllib.request.urlopen` accepts arbitrary schemes including `file://`,
which Bandit B310 flags as a path-traversal vector. The script's typical
caller is the maintainer's own shell, but a typo in `--restart-url`
could surprise — and the static gate is right to flag it. Validate the
scheme is http/https before the urlopen call and annotate it so Bandit
accepts the now-truthful narrowing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 21:00:34 +02:00
malkuthro f8f8adf55d Use KForge spotlight as onboarding front door (#124)
* docs: use KForge spotlight and refresh guide showcases

* docs: address guide showcase review polish

* docs: fix auto-save showcase anchor
2026-05-10 21:16:19 +02:00
malkuthroandClaude Opus 4.7 8bbedfe3f7 docs: host visual guide on GitHub Pages, retire wiki URL (#117)
The bundled visual sidebar guide is now also live at
https://malkuthro.github.io/ComfyUI-Koolook/web/guide/ — pulled from main
via GitHub Pages (legacy mode, source=main/, enabled out-of-band via the
repos/.../pages API).

README's "get started" and "Learn More" sections, plus pyproject.toml's
Documentation URL (used by the Comfy Registry package page), now point
at the Pages site instead of the unmaintained wiki. The in-app Tools →
Help (`H`) button continues to open the bundled local copy via
`import.meta.url`, so the guide still works offline.

While here, fixed README's stale "Tools → Info" wording — the actual
button has the H help glyph and a tooltip reading "Open the Kforge Labs
visual guide" (verified in web/sidebar/tree.js).

Closes the wiki-URL part of #114; the rest of #114 (cross-ref polish,
glossary, snapshot-schema reference page) stays open.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:23:15 +02:00
malkuthro 27705be037 feat(sidebar): add onboarding guide (#107)
* feat(sidebar): add onboarding guide

* docs(guide): clarify tag search casing

* docs(guide): clarify workflow save copy

* docs(guide): refine sidebar visuals

* docs(guide): refresh save snapshot visual

* docs(guide): refresh load snapshot visual

* docs(guide): refresh module save visual

* docs(guide): use real sidebar screenshot

* docs(guide): render sidebar overview screenshot directly

* docs(guide): soften sidebar overview annotations

* docs(guide): clarify nodes action bar callout

* docs(guide): clarify workflow action bar callout

* docs(guide): simplify sidebar overview markers

* docs(guide): align sidebar overview intro

* docs(guide): use real snapshot recipe screenshots

* docs(guide): simplify project workflow diagram

* docs(guide): make function cards scannable

* docs(guide): sketch module recipe icon focus

* docs(guide): use real icon screenshot for module recipe

* docs(guide): add cropped workflow action screenshot

* docs(guide): use full toolbar screenshot for module recipe

* docs(guide): use real search screenshot

* docs(guide): use real node search screenshot

* docs(guide): standardize screenshot recipe cards

* docs(guide): tighten recipe callout styling

* docs: require visual QA for UI work

* docs(guide): address pass-2 review nits
2026-05-08 13:44:55 +02:00
malkuthroandClaude Opus 4.7 428d4f538b chore(nodes): drop Easy_Version + bump 0.1.9 (#41)
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>
2026-05-04 00:10:39 +02:00
malkuthroandClaude Opus 4.7 b7a17b570b chore(categories): split Koolook/VFX into Pipeline / Image / VAE + fix VAE display names (#38)
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>
2026-05-03 23:45:36 +02:00
malkuthroandClaude Opus 4.7 ee8ccefdf8 docs(reorg) + chore: roll [Unreleased] forward + bump 0.1.7 (#37)
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>
2026-05-03 23:26:46 +02:00
malkuthroandClaude Opus 4.7 f57ea38b71 feat(EasyResize): rename to EasyResize_Koolook + proper KJ Nodes attribution (#35)
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>
2026-05-03 23:09:04 +02:00
malkuthroandClaude Opus 4.7 60e90ec6c8 Release v0.1.5: registry hygiene + drop unused v1_0_1 Radiance fork (44 nodes → 8) (#34)
* 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>
2026-05-03 22:18:24 +02:00
malkuthroandClaude Opus 4.7 5881e8a808 Release v0.1.3: GPL-3.0 relicense, Easy_hdr_VAE_encode/decode (v2.3 fork), license/fork skills (#33)
* 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>
2026-05-03 21:40:41 +02:00
malkuthroandClaude Opus 4.7 3ad73aac3a docs: add RELEASING.md as canonical release procedure (#32)
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>
2026-05-03 17:13:59 +02:00
malkuthro 9069560379 docs+chore: README sync, sibling-projects pattern, skill, and path-leak cleanup (#27)
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/.
2026-05-01 10:59:42 +02:00
malkuthro 52712f05b6 Align release references and define clean tagging policy.
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
2026-04-24 15:56:30 +02:00
malkuthro 7f8eda4809 Restructure fork tracking and versioned Radiance layout.
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
2026-04-24 15:45:04 +02:00
kflame99 075ef223e8 Remove RunPod scaffold from public repo after private migration 2026-02-15 14:54:53 +00:00
kflame99 f3f87eba1d Address PR feedback: lock parsing safety, token auth, and path refs 2026-02-15 13:19:58 +00:00
kflame99 29cae9672d feat(runpod): scaffold reproducible RunPod ComfyUI setup 2026-02-14 23:08:04 +00:00
malkuthro 7e159780fe chore: add release workflow and third-party tracking scaffold 2026-02-14 22:42:12 +00:00
malkuthro 46f78cf7bc Readme update 2025-10-04 15:42:28 +02:00
malkuthro f24db5ce96 update README 2025-09-28 23:31:23 +02:00
malkuthro 51dd290912 add readme 2025-09-28 14:53:49 +02:00