dependabot/github_actions/github-actions-30f7f1d3b7
12
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4add6af5bc |
chore(deps): bump the github-actions group across 1 directory with 5 updates
Bumps the github-actions group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/checkout](https://github.com/actions/checkout) | `7.0.0` | `7.0.1` | | [actions/setup-python](https://github.com/actions/setup-python) | `6.2.0` | `7.0.0` | | [actions/setup-node](https://github.com/actions/setup-node) | `6.4.0` | `7.0.0` | | [github/codeql-action/init](https://github.com/github/codeql-action) | `3.37.6` | `4.37.9` | | [github/codeql-action/analyze](https://github.com/github/codeql-action) | `3.37.6` | `4.37.9` | Updates `actions/checkout` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1) Updates `actions/setup-python` from 6.2.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/a309ff8b426b58ec0e2a45f0f869d46889d02405...5fda3b95a4ea91299a34e894583c3862153e4b97) Updates `actions/setup-node` from 6.4.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...820762786026740c76f36085b0efc47a31fe5020) Updates `github/codeql-action/init` from 3.37.6 to 4.37.9 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/c4dd10e44af883a891fe31ced449bcb4a6728b9b...cdf488f595d80d6e07e03d4674febd5ab45fa938) Updates `github/codeql-action/analyze` from 3.37.6 to 4.37.9 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/c4dd10e44af883a891fe31ced449bcb4a6728b9b...cdf488f595d80d6e07e03d4674febd5ab45fa938) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/setup-node dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/setup-python dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: github/codeql-action/analyze dependency-version: 4.37.5 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: github/codeql-action/init dependency-version: 4.37.5 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> |
||
|
|
2babbafb6b |
chore(security): pin Actions and harden test lock (#273)
* chore(security): pin Actions and update aiohttp * fix(security): generate universal test lock * fix(security): harden relock safeguards |
||
|
|
29052ed369 | ci: update actions for Node 24 runtime (#262) | ||
|
|
bda4df576a |
Release v0.4.1 (#250)
* Release v0.4.0: update footer notice * Release v0.4.1 |
||
|
|
e165c96fcc | fix(ci): enforce dependency audit gate (#247) | ||
|
|
c6a155a033 |
fix(web): generation-agnostic Comfy draft-quota guard (#237)
* fix(web): generation-agnostic Comfy draft-quota guard "Failed to save workflow draft" toasts returned on ComfyUI frontend 1.44+ because draft storage moved to new localStorage key names (per-workspace V1 keys, then a V2 index+payload scheme) that the old exact-name guard embedded in ltx_director.js never matched - and the 1.44 V2 layer latches a session-wide storage-unavailable flag after one failed save+evict cycle, re-toasting on every edit until reload. Move the guard to its own global extension, web/koolook_draft_guard.js: - match draft keys by prefix (Comfy.Workflow.Draft) across all known generations, with unknown future keys as last-resort evictions - rescue quota failures inside localStorage.setItem (evict the oldest draft across generations, retry) before Comfy's own catch sees the error, so the save succeeds and the latch never trips - boot prune: drop the suffixed-V1 dead weight the frontend's V1->V2 migration never deletes, scope corrupt-key cleanup to the offending key, drop oversized entries, enforce a total draft budget - ship the guard with dev-sync-audio so a scoped sync cannot strand a dev install guard-less Behavior is covered by tests/js/test_draft_guard.mjs (12 scenarios, wired into CI next to the existing node smoke test); static integration contracts live in tests/sidebar/test_draft_guard.py. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(web): address deep-review findings on the draft guard - latch the "still full" hint toast once per session so a genuinely full origin cannot re-toast on repeated failing autosave attempts; regression assertion added to the exhaustion scenario - document the bounded-eviction termination contract and the post-rethrow storage-unavailable latch at the wrapper, plus the budget's V1-blob-only (1.5M) -> all-generations (2M) scope widening (also now stated in the CHANGELOG entry) - version-robust wording for the suffixed-V1 cleanup rationale: the shipped 1.44 migration leaves the keys behind (verified against the installed 1.44.19 dist - no removeItem exists there), later frontends clean up on successful migration, and an interrupted migration can leak the keys on any version - comment the intentional best-effort swallow in the toast helper Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
5da590120c |
fix(tests): canonicalize expected writer filepath on Windows (#238)
* fix(tests): canonicalize expected writer filepath on Windows build_pipeline_outputs canonicalizes output paths to forward slashes on every platform, but the execution-map writer test built its expectation from str(tmp_path), which yields backslashes on Windows — failing there while ubuntu CI stayed green. Normalize the expected prefix the same way test_easy_ai_pipeline.py already does. No-op on POSIX. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: run pytest job on a windows-latest matrix lane The suite is now Windows-clean (previous commit), but only ubuntu ran in CI - the path-separator regression this PR fixes was invisible until a local Windows run. Add windows-latest to the pytest job so that class of break gates PRs. fail-fast off so a Windows-only failure still reports alongside the green ubuntu lane. Safe rename: Protect-main requires only "Lint & Smoke" and "Security Gate", so Pytest -> "Pytest (os)" breaks no required check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
201cdf3001 |
Track audio loop card setup metadata (#191)
* feat(audio): surface director flavor and prompt mode * Track audio loop card setup metadata * Fix audio card review issues * Harden audio card metadata capture |
||
|
|
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> |
||
|
|
8e489ad37a |
feat(snapshot): redesigned Save/Load dialogs + folder picker (#137) (#144)
* feat(snapshot): row-augment max(periodic, pre_load_*) + pytest infra (#137) Server-side preparation for the snapshot dialogs redesign. The Load dialog's "newer auto-save available" row flag now reflects the freshest recovery file regardless of which mechanism wrote it — before this we only stat'd ``periodic.json``, missing cases where the user's most recent Load wrote a fresher ``pre_load_*.json`` snapshot inside the same autosave subfolder. Extracts ``_latest_autosave_mtime(autosave_dir, named_mtime)`` from the inline block in ``list_presets`` so the scan is unit-testable. The helper walks ``periodic.json`` and every ``pre_load_*.json`` once, returns the max mtime if strictly newer than the named file, else ``None``. Same shape as before, broader source set. Introduces pytest as a first-class test runner: * ``tests/server/test_listing_autosave_mtime.py`` — 5 row-augment test cases (periodic-only, pre_load-only, max-of-both, no-newer, missing-dir). * ``[tool.pytest.ini_options]`` in ``pyproject.toml`` scopes discovery to ``tests/`` and uses ``importmode=importlib``. * ``[project.optional-dependencies] test = [...]`` defines the test extra (pytest + aiohttp, which is a runtime dep of ``koolook_routes`` that must be importable even when only a pure helper is under test). * ``.github/workflows/ci.yml`` gains a ``pytest`` job that installs via ``pip install .[test]`` and runs ``pytest -q``. Guards ``__init__.py``'s relative imports in a ``try / except ImportError / else`` block. Pytest's package collector walks up from test files looking for ``__init__.py`` and tries to import the one at the repo root — but the relative imports inside it only resolve under ComfyUI's custom-node loader, not under a standalone Python import. Without the guard, every pytest run aborts during collection with ``attempted relative import with no known parent package``. The fallback emits a one-line diagnostic and registers empty mappings so the package directory can still be imported by tooling. ComfyUI's loader still hits the ``else`` branch and behaviour is unchanged for real users. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(snapshot): folder picker + agent-driven visual harness (#137) Commit 2 of the snapshot dialogs redesign. Introduces the navigate- into folder picker from mockup section 6 — the picker that opens when the user clicks Save to… / Load from… in the redesigned dialogs (and that the Settings cog will be removed in favour of, once commit 6 lands). Path input is the source of truth: type/paste + Enter navigates, clicking a folder row drills in, ↑ Up climbs one level. Files appear greyed below the directories as a "yes, this is the folder I expected" affordance. End-visible path overflow: the path input uses ``direction: rtl`` + ``unicode-bidi: plaintext`` so when the path exceeds the input width the leading ``/Users/…`` clips on the left, never the trailing folder name. Per mockup section 6. Visual harness — the path the issue called out as "visual verification is a hard gate": * ``.claude/launch.json`` defines ``design-server`` (``python3 -m http.server 8765``). Agent / maintainer can spin this up via ``preview_start`` or directly from a terminal. * ``docs/designs/_harness/folder-picker.html`` mounts the real ``showFolderPicker`` from ``web/sidebar/modals.js`` against a canned filesystem, with one trigger button per mockup-illustrated state (default / new-folder-input / empty / error). Cache-busts module imports so editing modals.js while the harness is open picks up fresh code on reload. * ``docs/maintainers/visual-harness.md`` documents the workflow, when to use the harness vs. dev-sync, and the backtick-in-CSS- comments pitfall that broke this commit twice during development. * ``CLAUDE.md`` now lists the harness as the preferred agent-driven path; dev-sync stays the integration-level gate. Server: ``/koolook/presets/browse`` gains an opt-in ``?files=1`` parameter that returns child JSON files alongside the directories. Default response shape unchanged so the legacy Settings dialog keeps working. ``_list_child_files`` mirrors ``_list_child_dirs``'s swallow-OSError-per-entry policy so a broken symlink mid-listing doesn't sink the whole response. Tests: six new pytest cases in ``tests/server/test_browse_list_children.py`` covering directory sorting, autosave-subfolder hiding, JSON-only filter, case-insensitive extension match, and the empty-result paths. ``pytest`` runs all 11 tests cleanly under the existing CI job from commit 1. What's still verified via dev-sync (not via the harness): * Real Comfy theme tokens (the harness fakes ``--comfy-menu-bg`` etc. with dark-theme defaults). * End-to-end Save → Load round-trip across the new library path. * Picker interaction with ComfyUI's keyboard manager. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(snapshot): modal headers stay title-only; route gloss to tooltip (#137) Follow-up to the folder picker commit. Maintainer flagged that the "Where snapshots are saved and loaded from." subtitle below the title was extra information the user doesn't need at first glance — if the title isn't self-explanatory, fix the title, don't pad it with a sentence. The mockup at docs/designs/snapshot-dialogs.html section 6 shows a title-only header for exactly this reason. Locks the rule in as a project convention so every dialog box behaves the same way going forward: * docs/maintainers/conventions.md — new "Modal headers" section spells out the rule, what counts as a "descriptive subtitle" (remove) vs. a "functional info row" (keep), and how to plumb explanatory copy via a hover tooltip on the title instead. * web/sidebar/modals.js — makeModalShell now accepts ``titleTooltip``, applied as the ``title`` attribute on the modal title element so the gloss is mouseover-discoverable but never visible by default. showFolderPicker drops its ``subtitle`` param (it was added one commit ago, no other callers) in favour of ``titleTooltip``. * docs/designs/_harness/folder-picker.html — harness re-points its explanatory text to ``titleTooltip``. Verified in the harness: the visible header is title-only, the tooltip surfaces on hover. Applies prospectively to the Save / Load dialogs (commits 3 and 4) — they will also be title-only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(snapshot): redesigned Save dialog with inline library row + Save to... + 4-state button (#137) Commit 3 of the snapshot dialogs redesign. The Save dialog is now a single modal (was three: three-way overwrite / input prompt / confirm) that matches mockup section 2: * Inline library-path info row at the top of the body — "Saved to" label on the left, "Open folder ↗" link on the right, full path below. Pure information; every action lives in the bottom command bar. * Bottom command bar with split layout: Save to... on the left, Cancel + Save as new... + Save on the right (spacer in between). * Save to... opens the folder picker from commit 2. On Use this folder, the dialog calls saveSettings() to persist the new library path, refreshes its in-place library row, and flips the primary button into Dirty state. * The primary Save button cycles through the four states from mockup section 5: - Default ("Save") — clean state, primary blue. - Dirty ("Save to new folder") — folder differs from the one the dialog opened with; the label spells out the consequence. - In progress ("Saving...") — disabled, dimmed primary. - Done ("Saved") — disabled, subtle green, brief pause before the dialog closes. * Save as new... still routes through the existing showInputModal plus presetExists guard, but the prompt no longer carries a library-path subtitle — the parent dialog already shows the target. Convention from the previous commit applied. tree.js now passes the new capability functions (saveSettings, browseDirectories, createBrowseDirectory, revealPresetFolder) into showSaveSnapshotDialog so the dialog can invoke the folder picker end-to-end inside the Save flow. Visual harness: docs/designs/_harness/save-dialog.html exercises all five mockup states (default tracked, untracked Save-as-new, dirty, in-progress, done) so the maintainer (or future agent) can re-verify without dev-syncing. Verified all states render correctly in the preview server. Static guard against the recurring backtick-in-CSS-comments trap: tests/sidebar/test_css_template_literal.py asserts that the CSS template literal in web/sidebar/constants.js contains exactly two backticks (open + close) and nothing in between. The trap bit this work three times (commits 2 and 3) — a literal backtick inside a comment closes the template early and silently bricks the entire sidebar. The test runs under the same pytest job introduced in commit 1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(snapshot): redesigned Load dialog with scoped recovery + inline delete (#137) Commit 4 of the snapshot dialogs redesign. The Load dialog is now a single modal matching mockup section 3: * Inline library row at the top, same shape as the Save dialog — "Loaded from" label + Open folder ↗ link + leaf folder name + full path. No 📂 emoji button (the link supersedes it). * Preset rows: click to load. The "Replace current state?" confirm modal is gone — clicking Load is the intent, the dialog title already says Load snapshot, no double-confirm. * Scoped recovery: when a preset has a newer autosave (per the server-side row-augment from commit 1), the first click DOES NOT load. It expands exactly ONE recovery row directly beneath the parent, showing the freshest entry (newest of periodic.json or pre_load_*.json) with its kind badge + meta line. The user then chooses: re-click the named row to load the named version, OR click the recovery row to restore the auto-save. Both options are surfaced inline; the user picks by clicking the one they want. * Inline delete confirm: × outlines the target row red, the bottom Close button transforms to 'Yes — delete "<name>"' (danger styling). A second click commits; Escape cancels and reverts. No second modal. * Bottom command bar matches mockup section 3 split layout: [Load from…] on the left, [Close] on the right. Load from… opens the folder picker from commit 2; on Use this folder it persists via saveSettings() and refreshes the listing. The pre-#137 YES/NO choice modal (``promptApplyChoice``) and the collapsible Recovery auto-saves <details> section are both removed — the scoped-recovery inline row + the click flow above subsume their job. (Commit 5 in the issue plan was specifically for dropping the YES/NO modal, which happens here as a natural consequence of the routing change; commit 5 will be a small follow-up if needed.) Behavior preserved from the pre-#137 implementation: * doNamedLoad — pre-load auto-save backup chain, partial-failure tracker handling, identical toast messages. * doAutosaveRestore — same backup chain, same markStateAutosaved() semantics, same restored-name derivation from subdir. Tree.js plumbs the three new caps (saveSettings, browseDirectories, createBrowseDirectory) into showLoadSnapshotDialog so the dialog can invoke the folder picker end-to-end. Visual harness: docs/designs/_harness/load-dialog.html exercises default, empty, scoped-recovery, and pending-delete states. Verified all four render correctly in the preview server. Net diff: -56 lines in the sidebar source (the redesign deletes more than it adds because the YES/NO modal + collapsible recovery disclosure + confirm modal for plain loads are all gone). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(designs): reconcile snapshot redesign sketch with shipped behaviour (#137) Commit 5 of the snapshot dialogs redesign. The code-level removal of the autosave-newer YES/NO modal happened in commit 4 as a natural consequence of the scoped-recovery inline row taking over its job; this commit reconciles the design docs so they describe what was actually built. docs/designs/snapshot-dialogs-redesign.md: * "What changes" item 4 reworded — the YES/NO modal is dropped; the affordance is now an inline scoped recovery row that opens directly beneath the clicked preset. * "What changes" gains items 2, 3, 5 covering the Save/Load dialog redesigns and the inline delete confirm that landed in commits 3 and 4. * Mermaid flow rewritten to reflect the new routing (preset click → scoped recovery expand → user picks named or recovery row), matching commit 4's onPresetClick implementation. docs/designs/snapshot-dialogs.html "Locked-in decisions": * Updated the autosave-modal item from "modal head reads X" to "modal — dropped" and explains the inline scoped recovery row replacement. * Added the title-only modal header convention (commit 2 follow-up) pointing to docs/maintainers/conventions.md. * Added a pointer to the visual harness workflow added in commit 2. No code changes — the YES/NO modal was already gone after commit 4. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(snapshot): remove Settings cog + showSnapshotSettingsDialog + CHANGELOG (#137) Final commit of the snapshot dialogs redesign. The Settings cog disappears from the Snapshot toolbar — the snapshot row is now status indicator | Load | Quick Save | Save, matching mockup section 1. Library-path management now lives inside the Save dialog ("Save to…") and Load dialog ("Load from…"), both of which open the folder picker introduced in commit 2 and persist via the existing `saveSettings` route. Removals: * `showSnapshotSettingsDialog` (~325 lines) — the dialog body, its inline directory browser, and the "save folder location" state machine. The same browse functionality lives in `showFolderPicker` now; the same persistence happens via `saveSettings()` called from inside Save / Load. * `showThreeWayDialog` (~45 lines) — only consumer was the pre-#137 Save flow (overwrite / Save as new / Cancel), which the redesigned Save dialog absorbed into its primary action bar. * `renderLibraryLocation` (~17 lines) — replaced by inline rendering in the Save and Load dialogs' library rows. * Settings cog toolbar button + `openSettingsDialog` wiring in tree.js (~12 lines). * Orphan `.koolook-browse-*`, `.koolook-path-input-row`, `.koolook-load-library-row*`, `.koolook-settings-save-note` CSS rules in constants.js (~16 lines) — only consumed by the removed dialog. `.koolook-settings-folder-name` and `.koolook-settings- folder-path` stay; the new Save / Load library rows reuse them verbatim (git-blame continuity for the visual style). Adds: * CHANGELOG.md [Unreleased] entry summarising the whole #137 feature — picker, redesigned Save/Load dialogs, scoped recovery, inline delete, removed Settings cog, pytest infrastructure. Net diff for this commit: -377 lines. Cumulative PR diff (commits 1–6 + harness/convention follow-ups): all six issue ACs satisfied. The maintainer should dev-sync once before merging to confirm real-Comfy theme tokens render correctly (harness fakes the dark-theme defaults) and end-to-end Save → Load round-trips against the live preset folder behave. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(ci): install pytest + aiohttp directly, not via pip install . (#137) The Pytest job introduced in commit 1 of this PR was failing on CI because ``pip install .[test]`` tries to build a wheel of the entire project. setuptools's flat-layout discovery then trips on the non-Python ``web/`` and ``forks/`` directories at the repo root and errors out with "Multiple top-level packages discovered in a flat- layout: ['web', 'forks']". The project is a ComfyUI custom node loaded directly from its source directory, not a pip-installable package. There's no wheel to build. Install the test deps explicitly instead — the ``[project.optional- dependencies] test`` block in pyproject.toml is the spec, CI mirrors it by hand. Worked locally because the venv install path went straight to ``pip install pytest aiohttp`` and never touched the project. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(snapshot): untracked dirty state + Load dialog Escape listener leak (#137) Two findings from the external review on PR #144: **Blocker — Save dialog's primary action with no tracked preset + folder changed via Save to...** ``updatePrimaryLabel`` was entering the "dirty" state whenever the library path diverged from the original, regardless of whether a tracked preset existed. The primary click handler then routed "dirty" to ``doOverwrite(current)`` — and with ``current === null``, ``sanitizeName(null)`` would throw / silently coerce to an empty string instead of asking the user for a name. Fix: ``isDirty()`` only matters when there is something to overwrite. With no tracked preset, the primary stays in ``default-new`` regardless of folder divergence. The Save to... button still updates the library row, so the user has feedback the destination changed; the eventual primary click then routes to the Save-as-new name prompt and writes into the new folder cleanly. Verified in the visual harness: opening Save as untracked, switching the library to ``/Volumes/Shared/different-library`` via the picker, then inspecting the primary button: * Label stays "Save" (was "Save to new folder" pre-fix) * Tooltip "Choose a name and write the snapshot." (was "Write into /Volumes/Shared/different-library.") * Library row still reflects the new path (saveSettings DID run) **Major — Load dialog leaked a document keydown listener per session** The inline-delete Escape-to-cancel handler was registered with ``document.addEventListener`` but never removed. Each open/close cycle of the Load dialog accumulated another stale handler; long sessions ended up firing the cancelDelete check on every Escape press across every dialog (no-op because ``pendingDelete`` was null in closed dialogs, but the listener was still alive and called). Fix: capture the handler by name, attach on open, tear down on close by wrapping ``overlay.remove`` (mirrors the pattern the modal shell already uses at ``modals.js:52-66`` for its own Escape handler). Verified by instrumenting ``document.{add,remove}EventListener`` and opening + closing the Load dialog five times in a row: every keydown listener added during the cycle was removed before the next cycle opened. No accumulation. CI gates: ruff, compileall, bandit (via preflight equivalent), pytest 12/12, preflight 4/4 — all green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
cc6bc47866 |
docs+tooling: VAE user guide + versioning ref + 3 skills + preflight CI (#48)
* 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>
|
||
|
|
7121094780 |
ci: add lint + bandit security gate, wire main protections (#29) (#30)
* 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>
|