v0.43.0 — Audit-driven polish + Civitai backfill CLI
v0.43.0 — Six rounds of audit-driven polish + Civitai backfill CLI
A condensed release covering grind-rounds A → G from a systematic codebase audit. Highlights below; no socket / widget / workflow JSON shape changes since v0.41.
Round A — security + perf wins
- Zip-bomb defence on
/import_zip— sums uncompressed sizes from each ZipInfo header before reading any member; rejects expansions over 2 GB. - CSV size cap (50 MB) on
/import_csv— was unbounded; now consistent with image (16 MB) and zip (500 MB) caps. /listdirectory cache —_image_path_forwas doing ~7 stat() calls per entry inside the list response (4900 syscalls for a 700-entry library per/list). Now oneos.scandirbuilds an id set per request.- JSON body validation — new
_json_payloadhelper centralises the inconsistent pattern across 5 POST routes; malformed bodies → 400 with a clear message instead of 500. Adds missingids must be a listcheck to/exportand/bulk_delete. - Atomic
prompt_logwrites — singleos.write(fd, line_bytes)+ fsync per JSONL line. Process crash mid-write can't corrupt the file anymore.
Round B — quality / consistency
- SHA256 hash-cache LRU capped at 4096 entries (~320 KB on disk).
- Named depth constants (
_TEXT_LINK_MAX_DEPTH,_PIPE_TRACE_MAX_DEPTH) replace bare4/8literals in the Civitai workflow walker. - Deep-copy loras on duplicate — was a shallow
[dict(l) for l in src["loras"]].
Round C — test coverage + a real bug
- End-to-end save → export → reimport round-trip test — caught a silent data-loss bug: the
negativefield was being exported but never read back on import. Fixed alongside. - New tests for
import_backgroundsandimport_tag_packsroutes. - 247 tests, was 242.
Round D — modal UX
- Independent CLIP-strength slider in the Edit Prompt modal — each LoRA row now has stacked
MandCslider+number pairs. Backend always trackedstrength_modelandstrength_clipseparately; the UI was silently mirroring them. Pre-v0.40.3 entries with onlystrength_modelsaved →strength_clipdefaults to the model value on load (mirror preserved as fallback). - Soft-delete on LoRA rows — Delete now toggles to "Restore"; row dims and strikes through but stays editable. Misclick is reversible without abandoning every other modal edit.
- Scene-node empty-output warning —
PromptLibraryScenewith every knob at(none)and emptyextraused to silently emit"". Now logs.
Round E — Comic Page + more tests
- Per-panel strength override on Comic Page (Regional) via a new optional
panel_strengthsCSV widget. Position N maps to panel N; blank/missing positions fall back to the global default. - 5 new PerPanelStrengthTests, 1 new WalkModelChainCycleTests, 1 new build_record-with-loras test.
- 254 tests, was 247.
Round F — small misc items
- LoRA Picker auto-detects ComfyUI's host:port from
PromptServer.instance.serverinstead of hardcoded127.0.0.1:8188. PromptLibraryRandom.IS_CHANGEDnow folds the prompts.json mtime into the cache key, so editing a tag-matched entry mid-session invalidates the cached pick at fixed seed too.- Watcher loop wraps each iteration in
try/except Exceptionso a future bug in_notify_changecan't kill the daemon and break gallery auto-refresh for the rest of the session.
Round G — Civitai metadata backfill CLI
python3 tools/civitai_backfill.py /path/to/output --recursive --verboseWalks a folder of PNGs, reads the workflow JSON Comfy embeds in the prompt chunk, computes SHA256 hashes for the model + LoRAs (cached on disk in the same data/hash_cache.json the live node uses), and rewrites the parameters chunk with a proper Civitai Hashes: {...} JSON block. Idempotent — already-tagged PNGs are skipped on re-run. Useful for a backlog of generations from before the Save node was wired in.
Designed to run independently of ComfyUI — no live server needed, no Python deps beyond Pillow.
Backward compat
All changes internal — no socket / widget / workflow JSON shape changes. Drop-in safe with v0.41.x and v0.42.x workflows.
Install / upgrade
cd ComfyUI/custom_nodes/ComfyUI-GrimmRibbity
git pull
# restart ComfyUI / hard-refresh browser tab