A fresh install ends its first library scan with a page full of grey
placeholder cards. This adds the bridge from "scanned" to "illustrated
library":
- FirstRunManager.start_initial_scan arms a bulk_fetch_prompt_pending
flag when the first scan actually launches. Upgrade shortcuts and the
defer path skip it — those users already have metadata, or have no
fresh scan to anchor the prompt to.
- New GET /api/lm/metadata-fetch-candidates reports how many cached
models per page type qualify for a bulk fetch. It is read-only
(in-memory cache only, never triggers a scan), excludes recipes, and
shares the eligibility predicate with BulkMetadataRefreshUseCase
(extracted as is_fetch_candidate/count_fetch_candidates), so the
advertised number matches what a fetch would actually process.
- BannerService shows a one-shot banner with the candidate count and a
Fetch Metadata action that runs the existing fetchCivitaiMetadata
flow (progress bar + reload included). The flag is cleared once the
banner displays, so it never nags twice; dismissal persists through
the shared dismissed_banners setting.
Onboarding conflict is avoided structurally: the banner registers only
from the showPromos branch, which already requires the onboarding tour
to be finished or skipped and the first-run/init pages to be gone, so
the tour and this prompt never compete for the same moment.