• bvandeusen released this 2026-05-26 08:28:01 -04:00 | 608 commits to dev since this release

    First release of 2026-05-26 (.0). Wraps up FC-Cleanup (Settings → Cleanup tab) end-to-end plus three production-impacting fixes flagged during the session.

    What's new

    FC-Cleanup tab — full feature

    New top-level Settings → Cleanup tab between Import and Maintenance:

    • Minimum dimensions — instant SQL preview + Tier-C delete-min-dim-<sha8> confirm. Defaults pre-fill from ImportSettings.min_width / min_height.
    • Transparency audit — async Celery scan with 5s polling; Tier-C delete-audit-<id> confirm to delete matched images. Animated WebP/GIF short-circuit (no multi-frame PIL decode).
    • Single-color audit — same async pattern; threshold + tolerance inputs. First canonical implementation of the rule (import-side filter was unimplemented).
    • Tag maintenance — moved as-is from Maintenance tab. prune_unused_tags flow unchanged.

    Backend: 9 endpoints under /api/cleanup/*, new cleanup_service.start_audit_run / apply_audit_run / cancel_audit_run, new scan_library_for_rule Celery task on maintenance queue (soft_time_limit=7200, time_limit=7500, 50k matched-IDs cap, cancellation check between batches). Inherits FC-3i task_run lifecycle.

    Defaults pre-fill from ImportSettings; operator can override per-audit.

    Worker UniqueViolation crash fix

    Concurrent workers processing different files of the same post both did check-then-INSERT on Source, second one tripped uq_source_artist_platform_url, session poisoned, every subsequent op failed with "transaction has been rolled back". New _find_or_create_source + _find_or_create_post helpers in Importer use SQLAlchemy savepoints (begin_nested()); on IntegrityError, the savepoint rolls back (outer transaction preserved) and a re-select picks up the row the concurrent op committed.

    Error display flat-text + copyable

    SystemActivityTab and ImportTaskList previously used :title="..." to surface full SQLAlchemy traceback content as a browser-native tooltip — uncopyable, unscrollable, cramped. Replaced with ErrorDetailModal: click error → modal with <pre> block + copy-to-clipboard button + scroll cap.

    Firefox extension install button now works

    Install button switched from window.location.assign(url) (programmatic) to :href="manifest.latest_url" (real anchor click). Firefox's XPI-install gesture requires a directly user-clicked anchor pointing at application/x-xpinstall. Also: manifest endpoint now excludes the -latest.xpi alias from version-detection (was tying mtime sort, yielding cosmetic · Firefox · v latest).

    Memory banked

    • reference-forgejo-auto-merge-pins-commitmerge_when_checks_succeed pins to PR head SHA, not whatever dev HEAD is at CI-pass. Don't push to dev while a PR is queued.
    • reference-image-record-sha256-fixture — sha256 column is varchar(64); fake fixtures use ljust(64,...)[:64].
    • reference-calver-today-date — CalVer tag is based on CUT-DAY's date; .N resets each day. Don't carry over .N from yesterday's tag.

    Schema changes

    None new this release. Migration 0020_library_audit_run was already in v26.05.25.6; FC-Cleanup just wires API + UI to consume it.

    Verification post-deploy

    1. Settings → Cleanup tab present between Import and Maintenance, four cards render
    2. Min-dimension Preview returns a count; Delete with token works
    3. Transparency audit Scan kicks off, polling shows scanned/matched counters tick up, Apply with token deletes
    4. Import worker no longer crashes on concurrent Source insertions (verify by triggering a deep scan of /import that touches a multi-file post)
    5. Click an error in System Activity → modal opens with full text + Copy button
    6. Settings → Overview → "Install Firefox extension" → Firefox shows the standard install prompt; card displays · Firefox · v1.0.3

    🤖 Generated with Claude Code

    Downloads