* 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>
119 lines
5.7 KiB
Bash
119 lines
5.7 KiB
Bash
# 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=
|
|
|
|
# --- Snapshot / preset library ----------------------------------------------
|
|
# Where the Kforge Labs snapshot library lives on disk. A "snapshot" is a
|
|
# named JSON file containing your full Kforge Labs state (curated picks +
|
|
# all workflows). Saved snapshots become the preset library you can
|
|
# Load / Save / Manage from the sidebar's top action bar.
|
|
#
|
|
# Default if unset: `<comfyui-userdata>/koolook-presets/`
|
|
# — fine for personal use; libraries stay per-install.
|
|
# Set to point at a shared location if you want:
|
|
# - Cross-machine personal sync: a Dropbox/iCloud/Drive folder
|
|
# - Facility shared library: an NFS/SMB mount writable by every
|
|
# workstation, so all of them save to + load from the same library.
|
|
#
|
|
# Note: this var differs from the rest of the KOLOOK_* prefix on purpose —
|
|
# it carries the Kforge Labs branding (the user-facing tab name) so a
|
|
# facility deployment doc can refer to it without code-name baggage.
|
|
#
|
|
# Examples:
|
|
# macOS personal sync: /Users/<you>/Dropbox/koolook-presets
|
|
# Linux NFS facility: /mnt/facility-shared/koolook-presets
|
|
# Windows SMB facility: Z:/facility/koolook-presets
|
|
#
|
|
# The directory is auto-created on first save (its parent must already
|
|
# exist). Read-only mounts are detected — saves fail cleanly with the
|
|
# server-side reason in a toast; loads still work.
|
|
KFORGELABS_PRESETS=
|
|
|
|
# --- Local dev sync ---------------------------------------------------------
|
|
# Path to the eventual Koolook subdirectory inside your 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). Point at the leaf, NOT the parent — the parent
|
|
# `custom_nodes/` must already exist; the script can create the leaf
|
|
# itself with `--init` on first run. Leave unset to disable; the script
|
|
# errors out cleanly if invoked without it. Forward slashes work on
|
|
# Windows too. No default — entirely user-specific.
|
|
#
|
|
# IMPORTANT: target `custom_nodes/koolook/`, NOT `custom_nodes/ComfyUI-Koolook/`.
|
|
# The ComfyUI Manager / Registry install creates `koolook/` (derived from
|
|
# `[project].name` in our pyproject.toml). Pointing dev-sync at the same
|
|
# leaf overwrites the Manager install in place — that's what you want.
|
|
# Targeting `ComfyUI-Koolook/` instead creates a second parallel install,
|
|
# and ComfyUI loads BOTH on every boot — the `__init__.py` duplicate-install
|
|
# guard will print a critical log naming both paths and disable the
|
|
# non-winning copy, but the cleanest path is to never create the dual
|
|
# install in the first place. See issue #162 for the full failure mode.
|
|
#
|
|
# Examples:
|
|
# macOS: /Volumes/Data/ComfyUI/custom_nodes/koolook
|
|
# Linux: /home/<user>/ComfyUI/custom_nodes/koolook
|
|
# Windows: C:/ComfyUI_portable/ComfyUI/custom_nodes/koolook
|
|
#
|
|
# First-run on a fresh machine:
|
|
# 1. Set the variable here.
|
|
# 2. `python scripts/sync_to_dev.py --init` (creates the leaf folder)
|
|
# 3. From then on, plain `python scripts/sync_to_dev.py` is enough.
|
|
KOLOOK_COMFYUI_DEV_PATH=
|
|
|
|
# --- Automations working folder ---------------------------------------------
|
|
# Per-project "everything in one place" folder used by the AI-assisted
|
|
# iteration loop under `automations/`. Holds: the workflow JSON exported
|
|
# from ComfyUI, the rendered video, the generated `card.png`, and
|
|
# `iterations.md` (append-only log). One folder = one project.
|
|
#
|
|
# See `automations/CONVENTIONS.md` for the full contract.
|
|
#
|
|
# Read by:
|
|
# - automations/scripts/make_card.py (fallback when the workflow JSON
|
|
# has no `Working_Folder_PATH` Text Multiline node).
|
|
# - the `/make-card` skill (.claude/skills/make-card/SKILL.md) to find
|
|
# the newest workflow JSON to render a card for.
|
|
#
|
|
# Update this when switching projects. Forward slashes work on Windows.
|
|
# No default — leaving it unset disables the `/make-card` skill's
|
|
# auto-discovery; you can still call `make_card.py <wf.json>` directly
|
|
# and the script will use the JSON's parent directory.
|
|
#
|
|
# Examples:
|
|
# macOS: /Volumes/Data/JOBS/<client>/<scene>/ComfyUI-working-folder
|
|
# Linux: /home/<user>/JOBS/<client>/<scene>/ComfyUI-working-folder
|
|
# Windows: N:/JOBS/<client>/<scene>/ComfyUI-working-folder
|
|
KOLOOK_AUTOMATIONS_WORK_DIR=
|
|
|
|
# Optional: override the ComfyUI log path used by `make_card.py` to extract
|
|
# render durations. By default the script infers the log location from
|
|
# KOLOOK_COMFYUI_DEV_PATH (assumes <comfyui-root>/user/comfyui.log). Set this
|
|
# only if your install writes logs elsewhere.
|
|
KOLOOK_COMFYUI_LOG=
|