Import Comfy Gallery standalone application #1

Merged
scruffydude merged 99 commits from bugsy/initial-comfy-gallery into main 2026-09-09 12:36:49 -04:00 AGit
Collaborator

Extract Comfy Gallery from homelab with preserved app history, standalone container build, app tests, and Forgejo image publishing CI.

Extract Comfy Gallery from homelab with preserved app history, standalone container build, app tests, and Forgejo image publishing CI.
Swipe left/right/up/down to sort inbox items into SFW/Spicy/Skip/Trash
on touch devices, with a drag-follow card and direction stamps. Moves
curation buttons to a thumb-reachable bottom bar on mobile.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The floating toast/lastAction popup could sit over the lightbox image,
so it's gone entirely. Undo now lives as a small button in the lightbox
header that only appears after a curation move, never overlapping the
photo. Random also moves to a floating bottom-right button in the
read-only gallery/spicy lightboxes, out of the cramped header row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Android Chrome's toolbar eats a lot of the screen for a gallery app,
so this gives two ways to reclaim it: a web manifest (served per-
instance from FastAPI so each of gallery/spicy/curator gets its own
name) with standalone/fullscreen display for "Add to Home Screen",
and a Fullscreen API toggle in the main header for anyone just using
it in a browser tab. Icons are hand-drawn PNGs (no image toolchain
available) baked into the Docker image alongside the frontend build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The curator lightbox's icon row was wrapping to two lines on phones.
Download is dropped (available elsewhere in the inspector/card views),
Random moves into a new 3-dot overflow menu, and the row gap is
tightened. The circular prev/next arrows overlaying the photo are
gone too — navigation and zoom now live solely in the header, which
already had prev/next buttons; swipe paging still works unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Relocates prompt-library.yml/prompt-bundles.yml from aibench-local disk to
the NAS, folds prompt_librarian_web's backend and frontend into curator's
FastAPI/React app (gated behind CAN_WRITE so viewer instances are
unaffected), and adds a new recipe editor for the ComfyUI daily-generator's
recipe presets (recipes.yml, seeded with the 7 existing anima/checkpoint
recipes), wired into the generator-run trigger via a forced_recipe override.

prompt_librarian_web on channel66 keeps running in parallel against the
same relocated data until a later cutover.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds an on-demand "Animate this image" action and a nightly random-pick
cron generator, both driven by a new clean Wan2.2 I2V-A14B GGUF checkpoint
(QuantStack quant) instead of the existing unvalidated "Enhanced NSFW
Lightning Edition" I2V workflow, which shares the buggy merge family
already fixed once in the T2V pipeline. Threads a source image through
the generator/recipe engine via a new image_node config concept.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New page diffing Civitai favorites against what's actually installed on
aibench's models directory, for disk-space management: which LoRAs are
installed+favorited, favorited-but-not-downloaded ("back pocket", costs no
disk space), and installed-but-no-longer-favorited ("orphaned", prune
candidates). Also exposes a "sync now" action and, per-LoRA, the
wan_stage_manual pin added earlier this session -- lets you fix a
one-sided Wan MoE LoRA from the UI instead of SSH.

Backend: civitai_lora_bridge.py mirrors librarian_bridge.py's pattern
(importlib-load the already-rendered sync_civitai_loras.py from the host,
call its functions directly for reads; shell out to it for the actual sync,
mirroring /api/generator/run's lock-file+log+poll job pattern). No new
Docker mount needed -- the curator container already bind-mounts the whole
comfyui base dir. Added a restricted-permission token file
(comfyui.base_dir/.civitai_token, 0600) instead of baking the Civitai token
into the long-running container's environment, since docker inspect/exec
would otherwise expose it for the container's entire lifetime.

Frontend: new CivitaiBrowser.tsx page, wired into routing/nav like
Library/Recipes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Broadens the bridge beyond LoRA-only: list_installed() now scans every
managed asset directory (checkpoints, VAEs, embeddings, etc.), not just
loras/civitai, using the sync script's own managed_dirs_for_types() so the
scope stays in sync with what the sync script itself manages. Favorites
default to LORA+Checkpoint (the two types this pipeline actually manages in
volume) rather than crawling all ~19 Civitai asset types on every load.

Every item now carries a computed civitai_url (model + version) so the UI
can link out. Frontend groups installed/orphaned/favorited rows by model_id
(a model with multiple files -- Wan high/low pairs, multi-format checkpoints
-- collapses into one card instead of N flat rows), adds type and base-model
filter dropdowns, and a sort control (name/size/date installed/likes).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Restructures the grouping hierarchy: base model (Illustrious, Wan Video 2.2
T2V-A14B, Flux.1 D, etc.) -> asset type (Checkpoint vs LoRA) -> category
(style/situation/outfit/modifier/uncategorized) -> individual Civitai model
-> files. Mirrors the alias scheme the sync pipeline already computes
("civitai / {base_model} / {category} / {name}"), so everything tied to one
architecture -- checkpoints and every LoRA sub-component -- sits together
and can be reviewed or cleared out as a unit. Base-model sections default
collapsed (there are 15+ distinct ones) with a file-count/size summary;
per-file delete stays as-is rather than adding a bulk-delete action.

Also fixes a real latent bug found while wiring up the category lookup:
sync_now()'s --lora-categories-file fallback pointed at a path
("/data/user/default/lora-categories.yml") that never existed on this host
-- load_lora_categories() silently no-ops on a missing file, so every
"sync now" run from the browser was starting from an empty categories dict
and never persisting inferred categories. Fixed to the real host path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Favoriting on Civitai was previously a direct download trigger and prune
criterion: sync mirrored the full favorites list 1:1, so deleting a file
manually via the browser just got undone on the next sync (favoriting
doesn't change, so the "missing but still favorited" item just re-downloads).

New model: favoriting is discovery only. A separate local file
(civitai-selected.yml, alongside the existing lora-categories.yml) declares
which favorited models are actually wanted on disk. Sync -- both the
standalone playbook and the (currently dormant, sync_on_deploy: false)
deploy-time hook -- now downloads only what's selected, and prunes anything
installed that isn't. Deleting a file via the browser now also deselects its
model, so the deletion actually sticks.

Safety-critical migration: load_selected_models() auto-seeds the selection
file from whatever's *currently* installed the first time it's read (before
require_selection existed, prune was already unconditionally enabled in
prod config) -- otherwise turning this on would have pruned everything not
yet in an empty selection file. Verified with a synthetic test harness
against the actual modified functions (seed-on-first-use, persistence,
dry-run reporting vs real deletion) before deploying.

Also added --dry-run to the sync script itself and a "Preview" button in the
browser (calls it via POST /api/civitai/sync/preview) so a sync's effects
(would download/keep/prune counts, which files) can be checked before
committing to a real run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
sync_preview() used subprocess.run(timeout=120) inside a synchronous FastAPI
handler. A real dry-run against production data takes over two minutes
(Civitai API pagination, not local work), so every preview request hit the
timeout and crashed into an unhandled 500 -- confirmed live (HTTP 000/500
after exactly 120s).

Unified sync_now()/sync_preview() into one function with a dry_run flag,
reusing the exact same async Popen + lock-file + log pattern already used
for real syncs. The frontend now polls the same status endpoint either way;
sync_status() parses the sync script's final JSON summary line from the log
once the job finishes and returns it as `result`, so preview and real-sync
results render through the same code path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
sync.lock lives in STATE_DIR, which sits on the same host bind-mount the
whole comfyui base dir uses -- it survives a comfy_gallery container
rebuild. But the pid recorded in it is container-relative, so after a
rebuild that pid number can get reused by an unrelated process in the new
container, making sync_running()'s os.kill(pid, 0) check a false positive
forever (every future sync/preview click fails with "already running").
Several rebuilds happened back to back while fixing the preview timeout and
missing-curl bugs, which is exactly the scenario that creates this risk.

Add a time-based staleness check (15 min, well past the observed ~2-3 min
real run time) that clears the lock regardless of what the pid check says.
Also fixed: malformed lock data now clears the lock instead of just
returning False and leaving it in place forever.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Introduce a slide-out mobile navigation menu and a separate filters
dialog (via headlessui) so the gallery's controls are usable on
narrow viewports instead of relying on the desktop toolbar layout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The library was hard to navigate (prefix-only grouping, no cross-section
search), had no way to add an entry by hand (only the LLM-draft pipeline
existed), had no link between "situation" LoRAs and the prompt text they
need to look right despite 204/538 installed LoRAs being that category,
and LLM-assisted drafts were short and generic.

- Add an optional `tags` field to library entries plus a tag-chip filter,
  cross-section match indicator, and a one-time seed-from-prefix migration
  (already run against the live library, backed up first).
- Add a real "create entry" endpoint/form with a live Jaccard similarity
  check and a "clone from" action, since none existed before.
- Add a situation<->LoRA pairing table (lora-pairings.yml) editable from the
  situation entry, and wire the daily generator to guarantee a paired LoRA
  gets used when its situation is picked (soft bias -- other slots stay
  random). Verified the alias format against a live ComfyUI /object_info
  response on aibench (525/525 matched) and diffed generator output against
  the pre-change code across 20 seeds for the no-pairing case (identical).
- Ground LLM drafting in real library examples instead of a generic
  template, add a mandatory tightening critique pass over each batch, and
  shrink the default batch size so the model isn't stretched thin.
- Sync now skips modelVersions for base models nothing installed actually
  uses (comfyui.civitai_saved_loras.base_models allowlist), so a LoRA author
  publishing a new base-model release no longer silently queues a pending
  download for a model nobody has.
- Civitai browser sync preview gains a drag-and-drop review UI (@dnd-kit)
  for deciding per-asset actions before committing a sync.

Pre-existing working-tree changes from before this session, committed as-is
at the user's request -- not authored or verified in this session.
Reuses SECTION_HINTS' existing guidance/avoid lists so image extraction
respects the same section-purity rules as text drafting (asking for
"outfit" describes only clothing, not face/pose/setting). Wired into the
existing "Add entry" form as a suggestion the user reviews and applies
manually (same pattern as "Refine with AI"), never auto-created.

Uses qwen2.5vl:3b, the only vision-capable model currently installed --
tested against a real generated image: outfit extraction was usable but
leaked some background detail, subject extraction returned "nothing found"
on an image with a clearly visible face, so treat this as a rough starting
point to edit, not a reliable one-shot description. A larger vision model
would likely help but competes for the same ~10GB GPU as ComfyUI itself, so
left as a follow-up decision rather than pulling one unasked.
aibench's GPU is shared with ComfyUI generation (10GB total, often close to
full); WSL already runs Ollama with several 7-8B models comfortably and was
idle. Backend already accepted a per-request model/ollama_url override, so
this only needed a frontend dropdown -- no redeploy required to switch.

Pulled qwen2.5vl:7b onto the WSL instance (had no vision model before) and
verified end-to-end against the live curator API: noticeably better than
aibench's qwen2.5vl:3b on the same test image -- caught sash text the 3b
model missed, and correctly extracted hair/eye/skin details for "subject"
where the 3b model returned "nothing found" outright.
The "Commit changes" button never actually pushed anywhere -- commits sat
local-only on aibench's disk, which is also why that checkout could drift
100+ commits stale without anyone noticing (nothing forced it to talk to
origin). Replace the manual button with a debounced (10 min quiet period)
background sync-template + commit + pull --rebase + push, triggered by
hooking the single write_yaml() choke point every live-file write already
goes through, so no call site needed to remember to trigger it.

Mounts the previously-unused deploy SSH key into the curator container
(GIT_SSH_COMMAND) since nothing running inside it could push before this.
Verified against a real local git remote: debounce correctly collapses
rapid edits into one commit reflecting the latest state, and a concurrent
push from elsewhere rebases cleanly without losing either side.

Also adds a seed template + sync-template support for lora-pairings.yml,
which previously had no version-control backup at all (unlike the library
and bundles files), seeded from the pairings entered so far.
The container runs git as a different uid than owns the bind-mounted
checkout, which git refuses to touch by default ("detected dubious
ownership") -- and repo_status()/repo_commit() swallowed this silently
(bare nonzero exit, not an exception), so the old "Commit changes" button
had likely been reporting "Working tree clean" incorrectly this whole time,
which explains why it was never actually used to keep the seed templates
current. Whitelist the mounted checkout via safe.directory at import time,
and make the new auto-commit's status check fail loudly instead of quietly
no-op'ing if this ever recurs.
Discovered live: a fresh container has no git user.email/user.name at all,
so the auto-commit's own `git commit` failed outright on the very first
real run. Give it a distinct bot identity.
Just proved this gap live: a commit made during a prior failed attempt
(missing ssh client) sat local-only forever afterward, because the
function only checked "is the working tree dirty" to decide whether to
proceed -- once the tree was clean again, it never re-checked for commits
still sitting unpushed ahead of origin. Now checks @{u}..HEAD separately so
a stranded commit gets retried on the next debounce fire regardless of
whether anything new changed.
The old layout was five stacked navigation affordances (search, rating
filter, tag chips, "also matches in", prefix quick-jump pills) on top of
collapsible prefix-groups full of identical text-only cards -- structurally
a CRUD form over YAML, which is exactly what it felt like to use.

- New /api/library-previews endpoint: for a batch of keys, finds the most
  recent curated (sfw/spicy) image whose generation actually used that
  preset, by reading the generation.presets.<section> field every
  daily-generator sidecar already writes (write_sidecars() in
  comfyui_daily_generator.py) -- no new data plumbing, just surfacing what
  was already being recorded. Confirmed real scale (870 sidecars) makes a
  live per-request scan fast enough without needing an index.
- Library.tsx: entries render as a paginated thumbnail grid (60 at a time,
  "Load more") instead of every entry in every group rendered at once.
  Dropped the redundant prefix quick-jump-pills row now that tags cover
  the same discovery need. Moved bulk group actions (rename/mark sfw/mark
  nsfw/delete) out of an always-visible header repeated per group into a
  single collapsed "Bulk group actions" panel matching the existing
  Generate/Dedupe disclosure pattern, picked from a dropdown instead.
Overview stats and the search/rating/tag-chip toolbar were crowding the
main content column. Move them into the left sections sidebar, and
replace the entry edit/create modals with a persistent right-side
panel (matching the gallery's asset-inspector pattern) that includes a
one-click copy button for the prompt text.
The narrow left sidebar was too cramped for Overview/search once moved
there; put them back as full-width horizontal panels above the section
list instead, using the desktop's available width. Entry tiles are now
clickable anywhere (not just a small Edit button), and the right-side
edit panel scrolls internally so the Save/Delete row is always reachable
even when the panel content is taller than the viewport.

Also address app-wide image retrieval slowness: cache the curated-file
walk and file hashes behind duplicate detection (previously re-walked
and re-hashed the whole curated tree over NAS on every inbox listing),
cache the library-preview sidecar scan, and let the browser cache
/media responses long-term since curated files never change in place.
Library thumbnail previews now prefer an sfw-root image for sfw-tagged
entries, falling back to spicy only when no sfw image exists yet.
Overview and search/filter belong in the left sidebar as originally
requested -- restore that placement. The "smashed" complaint was about
the right-side edit panel: it was narrower (380px) than the modal it
replaced (max-w-lg, ~512px), so widen it to 480px and widen the
sidebar to 260px. Also step the entry grid down a column count when
the edit panel is open so tiles don't visually shrink into a
now-narrower main column.
These three utility panels sat open as three separate collapsed bars
at the top of every section, pushing the actual entry grid down before
you'd even seen a single prompt. Nest them under one outer disclosure
so they collapse to a single row by default; open drafts stay outside
it since that's content worth surfacing, not a tool to tuck away.
Replace the per-section tab navigation with a flat, paginated view
across all prompt sections at once (Bundles stays separate since it's
a different data shape). Section becomes an optional filter chip row
in the sidebar plus a badge on each card, instead of a mandatory
gate you have to pick before you can search.

Generate-more now has its own explicit section picker, since drafting
always targets exactly one section. Find-near-duplicates runs
library-wide (the backend already supported an unscoped scan). Bulk
group actions derive their target section from the group itself
(grouped by section+prefix), so no separate section state is needed
for those. Add-entry/Clone gained a section dropdown for the same
reason. Preview lookups and the "move to group" picker are now keyed
per-section so results stay correct across sections that reuse the
same key prefix.
Move the search input out of the sidebar into a prominent top bar.
The Sections filter chips now show live match counts for the current
search/tag query and drop out entirely once they have zero matches,
so narrowing down to relevant sections happens as a side effect of
searching instead of a separate step.

Also give the Library page the same full-window layout style as the
gallery/curator screens: a fixed-height shell with independently
scrolling sidebar/content/edit-panel columns instead of one long
scrolling document. Added as an opt-in `fill` variant on LibraryShell
so Review/Recipes/Civitai (not asked to change) keep their existing
scroll behavior.
Root cause of the slow image loading: generation output is served
straight off a CIFS NAS mount, full resolution (1-2MB PNGs), for every
tile in every grid (gallery browser, folder covers, Library previews).
Add a Pillow-based thumbnail generator (480px longest edge, JPEG q82,
~30-50x smaller) cached on local (non-NAS) disk per container, keyed
by path+size+mtime so a rename never serves a stale thumbnail. The
/media endpoint takes a `thumb=1` query param to opt into it; grid/cover
thumbnails in the gallery browser and Library previews now request
that, while the lightbox/detail full view is untouched.
The 259-entry lora_keywords section is trigger-word metadata, not
browsable prompts -- it was cluttering All prompts/section chips/counts.
Filtered out of orderedSections by default with a sidebar checkbox to
bring it back, so every downstream view (search, counts, chips) stays
in sync from one source.
Preview was a second 2-3 min live Civitai crawl on top of the page load
already crawling favorites synchronously on every open. Now favorites are
cached server-side with a background-refreshed TTL, and the three
disagreeing tabs (favorited/installed-derived) collapse into one list with
a per-item status (installed/pending_download/pending_removal/
favorited_only) computed instantly from local + cached state -- matching
exactly what selection already drives sync to do. Removals no longer need
a dry-run subprocess at all. The real sync now writes --log-file so
sync_status() can parse live per-model download progress instead of a
blank log until the final summary line.

Drops the whole preview/dry-run code path and the @dnd-kit/core
drag-and-drop keep/remove UI it required, since the checkbox already
updates the list live.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Turning on --log-file also activates sync_civitai_loras.py's
reset_log(), which truncates the log at the start of every run --
invalidating the byte offset captured before Popen (it pointed past the
now-shorter file), leaving log_tail/progress empty on a live sync.
Verified live on aibench: progress now populates correctly across a real
sync run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The running-sync panel was just a scrolling <pre> of log lines (including
raw curl progress-bar noise). _parse_sync_progress() now returns an
ordered queue of {model_id, name, status} instead of a status-only dict --
a model only enters the queue once the script's "selected variants" line
confirms it wasn't dropped as unselected/blocklisted, so the noise never
shows up as a queue entry. The frontend renders this as a real queue panel
(active downloads, failed list, live counts) with the raw log tucked into
a collapsed <details> for when it's still useful.

Verified live on aibench against a real sync run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Filters (status/type/base model/sort) were crammed into a single wrapping
row that left an awkward gap above the results -- moved into a left
sidebar matching the Library page's existing layout pattern.

Civitai split into two domains in 2026-04: civitai.com is SFW-only now,
civitai.red still shows NSFW. Almost everything this pipeline manages is
NSFW, so outbound "view on Civitai" links (both the web app's and the
sync script's) now point at civitai.red instead of 404/hiding for the
user. Also surfaces each model's first Civitai image (already available
in the favorites API response and in locally-stored version metadata,
just never captured before) as a thumbnail on every group and in the
Added/Removed sync result panel, so there's a visual to check before
deciding what to keep.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Grid video tiles were loading the full clip just to paint one frame, and
animated gif/webp had no way to tell them apart from static images in the
UI. ffmpeg now grabs a single frame near the start for video thumbnails
(same cache path as image thumbnails), animated images get a play/pause
toggle on the tile instead of always autoplaying, and the lightbox/detail
views load a blurred thumbnail first while the full-res original loads in
behind it. Grid also now paginates (60 at a time, "load more") instead of
rendering every item in the current folder at once.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Generating a LoRA training set (e.g. the Heibei bounty) means running
large ComfyUI batches into raw/training/<project>/ and then culling them
down to what's actually usable -- the same shape of problem the existing
sfw/spicy inbox curation already solves, just with a keep/delete binary
instead of a three-way split, and scoped per project instead of one
global inbox.

New /training page: project tabs sourced from raw/training/'s subfolders,
multi-select grid, batch Keep (moves into training/<project>/kept/ via
the existing /api/assets/move) and Delete (existing /api/assets/delete,
soft-moves to trash). No new curation primitives -- root_map() just
grows a "training" destination root alongside sfw/spicy/favorites/trash;
everything else reuses endpoints the inbox flow already exercises.

Verified with a real request against the live curator on aibench: folder
tree correctly found the 26-image heibei batch, and a move request
correctly relocated one file into training/heibei/kept/ with a sidecar.
Frontend typechecks clean (tsc --noEmit) and builds clean (vite build).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Grid-only view had no way to actually see an image full-size before
deciding keep/delete -- clicking a tile just toggled selection. Clicking
a tile now opens a full-size lightbox instead; the select checkbox moved
to its own click target (stopPropagation) so bulk multi-select still
works from the grid.

Lightbox adds single-image Keep/Delete (same move/delete calls as the
batch actions, applied to just the open item) plus prev/next navigation,
with keyboard shortcuts (K keep, D delete, arrow keys navigate, Esc
close) for reviewing a large batch one at a time without reaching for
the mouse between each. Removing the current item live-shrinks `items`,
so the lightbox index gets clamped/closed via effect rather than
pointing past the end of the array.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
# Conflicts:
#	ansible/roles/comfy_gallery/files/app/frontend/src/App.tsx
The single "Sync Now" button always bundled a favorites refresh, downloading
newly-selected models, and silently pruning any installed-but-unselected
model into one click with no confirmation. Split into three explicit
actions: Sync Likes (favorites refresh only, now also runs nightly),
Apply Downloads (never prunes), and a Review Removal modal that's the only
path allowed to bulk-delete from disk.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The Civitai Browser only ever showed the category the sync script
inferred at first-seen time, with no way to fix a wrong guess short of
hand-editing lora-categories.yml on the host. Add a category dropdown
per model in the browser, backed by a new PATCH /api/civitai/category
endpoint, and widen the sync script's keyword rules so fewer new LoRAs
land in "uncategorized" to begin with.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
get_save_image_path()'s counter is just "highest existing number in the
folder + 1" -- once curation moves a file out of inbox/raw, a later run
can recompute the same counter and silently reuse a filename a client
still has cached, showing old bytes at a URL that now points to a
different image. HomelabImageOutput now tags each save with a per-run
timestamp+uuid instead of a reused counter; the daily generator's
run_timestamp() parses the longer run-id format that produces; the
curator backend never caches inbox/raw URLs as immutable (only curated
paths, which are genuinely stable); and the lightbox tracks the loaded
image by URL instead of a plain boolean so switching images quickly
can't get stuck showing the previous one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The LoRA-linking picker in the curator's prompt library editor only
ever showed up for `situation` entries, even though the underlying
lora-pairings.yml store and API are keyed by an arbitrary string and
never actually required that. Extend the UI gate to also cover
`subject`, and teach comfyui_daily_generator.py to honor subject-keyed
pairings the same way it already does for situations, so linking a
character's LoRA to its subject entry actually biases nightly
generation toward it.

Also syncs the Ansible seed templates from the live prompt-library.yml
and lora-pairings.yml (yaniko subject/outfits/smoking situations added
directly on aibench, plus a yaniko -> its Civitai LoRA pairing to
exercise the new mechanism) since those live edits bypassed the
curator app's own auto-commit path.
# Conflicts:
#	README.md
Run app tests on pull requests
Some checks failed
Build and Push / test (pull_request) Successful in 1m16s
Build and Push / build-and-push (pull_request) Has been skipped
Build and Push / test (push) Successful in 1m28s
Build and Push / build-and-push (push) Failing after 4s
be24651d9e
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
scruffydude/comfy-gallery!1
No description provided.