soulsync/core
Broque Thomas 6cdcf778f3 Lift /api/automations/* into core/automation/
Routes moved to thin parse-args/jsonify handlers; logic now lives in
three focused modules under core/automation/. 436 lines deleted from
web_server.py; 53 added back as wrappers.

Module split:
- core/automation/api.py — CRUD + run + history helpers. Each function
  takes (database, automation_engine, ...) explicitly and returns
  (response_body, http_status). Includes signal cycle detection
  preflight checks for create + update.
- core/automation/progress.py — owns the in-memory progress state dict
  + lock (mirroring the original web_server.py globals as module-level
  shared state so all callers see one view), init/update/history
  helpers, and the WebSocket emit loop.
- core/automation/signals.py — collect_known_signals for the builder
  autocomplete.

Out of scope (deferred):
- _register_automation_handlers — the 23+ action handler closures stay
  in web_server.py because each one is tightly coupled to feature-
  specific implementations (wishlist, watchlist, library scan, etc.).
- Worker functions (_process_wishlist_automatically, etc.) — belong
  with their feature lifts.
- _run_sync_task / _run_playlist_discovery_worker — sync + discovery
  PRs.

Behavior preserved 1:1:
- Same route response shapes + status codes
- Same JSON field hydration (trigger_config, action_config,
  notify_config, last_result, then_actions)
- Same backward-compat: empty then_actions + notify_type set →
  synthesize then_actions from notify_type/notify_config
- Same signal cycle detection behavior on create + update
- Same system-automation protection on delete + duplicate
- Same reschedule/cancel logic on toggle + bulk-toggle + update
- Same progress state shape (status, progress, phase, current_item,
  log capped at 50, started_at/finished_at, action_type)
- Same emit-on-finish socketio push from update_progress
- Same emit loop semantics (1s tick, snapshot active states, reap
  finished after window)

Pre-existing bugs preserved (will fix in follow-up PRs):
- emit_progress_loop uses naive datetime.now() against tz-aware
  started_at/finished_at, so the timeout-zombie check raises
  TypeError → caught → never fires, and the cleanup-after-window
  check raises → caught → state is reaped on FIRST tick regardless
  of the window. Tests document this behavior so the next PR can
  flip them to the corrected expectation.

Tests: 72 new under tests/automation/ (signals 10, progress 24,
api 38). Full suite: 861 passing (was 789). Ruff clean.
2026-04-27 18:05:14 -07:00
..
automation Lift /api/automations/* into core/automation/ 2026-04-27 18:05:14 -07:00
imports Drop stale post-PR378 redefs and fix B009 2026-04-27 13:39:16 -07:00
metadata Tighten metadata and import safety 2026-04-27 20:28:05 +03:00
repair_jobs Fix Album Completeness job reporting zero findings for every album 2026-04-24 12:39:41 -07:00
search Search lift: pre-merge parity polish for cin's review 2026-04-27 15:32:48 -07:00
stats Lift /api/stats/* and /api/listening-stats/* into core/stats/ 2026-04-27 14:27:03 -07:00
acoustid_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
acoustid_verification.py Fix silent wrong-artist track downloads (Maduk/Tom Walker bug) 2026-04-22 10:32:55 -07:00
album_consistency.py Picard-style release preference scoring for MusicBrainz matching 2026-04-16 13:29:04 -07:00
api_call_tracker.py Make ApiCallTracker.save() atomic to prevent corrupt history files 2026-04-22 22:15:09 -07:00
artist_source_detail.py Extract _build_source_only_artist_detail into core/artist_source_detail.py 2026-04-23 08:09:29 -07:00
artist_source_lookup.py Make artist_name Optional in find_library_artist_for_source 2026-04-22 22:15:03 -07:00
audiodb_client.py Add API Rate Monitor dashboard with real-time speedometer gauges 2026-04-02 10:46:43 -07:00
audiodb_worker.py Add genre whitelist for filtering junk tags during enrichment 2026-04-18 20:23:53 -07:00
auto_import_worker.py Use parent folder name as artist override in auto-import 2026-04-20 22:56:34 -07:00
automation_engine.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
database_update_worker.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
deezer_client.py Fix playlist cover art not syncing to Plex/Jellyfin from Deezer and other sources 2026-04-15 10:25:38 -07:00
deezer_download_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
deezer_worker.py Fix Album Completeness job reporting zero findings for every album 2026-04-24 12:39:41 -07:00
discogs_client.py Fix Discogs cache — add field extractor, wire worker caching, browser UI 2026-04-02 19:47:36 -07:00
discogs_worker.py Discogs: count rows with empty type_ as real tracks too 2026-04-25 08:27:44 -07:00
download_orchestrator.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
genius_client.py Add API Rate Monitor dashboard with real-time speedometer gauges 2026-04-02 10:46:43 -07:00
genius_worker.py Improve graceful shutdown and rollback safety 2026-04-12 15:17:18 +03:00
genre_filter.py Expand default genre whitelist from 223 to 272 genres 2026-04-18 20:32:49 -07:00
hifi_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
hydrabase_client.py Add missing _get_artist_image_from_albums to HydrabaseClient 2026-03-23 17:54:21 -07:00
hydrabase_worker.py Improve graceful shutdown and rollback safety 2026-04-12 15:17:18 +03:00
itunes_client.py Fix iTunes album tracks failing on region-restricted releases 2026-04-20 11:10:54 -07:00
itunes_worker.py Fix Album Completeness job reporting zero findings for every album 2026-04-24 12:39:41 -07:00
jellyfin_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
lastfm_client.py Add Last.fm Track Radio to Discover page 2026-04-14 23:41:36 -07:00
lastfm_worker.py fix: stop enrichment workers from re-processing rows forever 2026-04-19 15:22:24 -07:00
library_reorganize.py Reorganize: fix moved-count + status/total UX issues from PR #377 review 2026-04-25 09:07:44 -07:00
lidarr_download_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
listenbrainz_client.py Remove emojis from all Python log and print statements 2026-04-11 21:11:02 -07:00
listenbrainz_manager.py Add Last.fm Track Radio to Discover page 2026-04-14 23:41:36 -07:00
listening_stats_worker.py fix: batch N+1 queries in listening stats worker 2026-04-19 15:22:25 -07:00
lyrics_client.py Remove emojis from all Python log and print statements 2026-04-11 21:11:02 -07:00
matching_engine.py Replace more print logs with proper logger usage 2026-04-21 14:42:21 +03:00
metadata_cache.py fix: batch metadata cache entity lookups 2026-04-19 15:22:24 -07:00
metadata_service.py Move single-track resolver; fix wishlist cleanup 2026-04-27 19:55:06 +03:00
musicbrainz_client.py MusicBrainz: Resolve release-group MBIDs to a release on album click 2026-04-24 08:48:02 -07:00
musicbrainz_search.py MusicBrainz: Dedupe same-named homonyms in artist search results 2026-04-24 10:27:45 -07:00
musicbrainz_service.py Add metadata cache maintenance and health monitoring 2026-03-30 07:40:20 -07:00
musicbrainz_worker.py fix: stop enrichment workers from re-processing rows forever 2026-04-19 15:22:24 -07:00
navidrome_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
personalized_playlists.py Replace all legacy metadata_service imports with canonical functions 2026-04-10 12:52:36 -07:00
plex_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
qobuz_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
qobuz_worker.py fix: stop enrichment workers from re-processing rows forever 2026-04-19 15:22:24 -07:00
reorganize_queue.py Reorganize queue: race + dedupe fixes from kettui review 2026-04-26 08:40:24 -07:00
reorganize_runner.py Library reorganize: FIFO queue with live status panel 2026-04-25 18:01:32 -07:00
repair_worker.py Rebuild Discography Backfill: auto-wishlist, Fix All, section UI 2026-04-21 18:44:43 -07:00
replaygain.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
runtime_state.py Tighten metadata and import safety 2026-04-27 20:28:05 +03:00
seasonal_discovery.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
socketio_cors.py Socket.IO CORS: handle self-review nits 2026-04-26 19:24:43 -07:00
soulid_worker.py Tighten legacy logging output 2026-04-21 18:00:31 +03:00
soulseek_client.py Rehome import helpers into core/imports 2026-04-27 19:54:44 +03:00
soulsync_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
spotify_client.py Bump Spotify post-ban cooldown from 5 min to 30 min 2026-04-24 16:07:26 -07:00
spotify_public_scraper.py Add Spotify Link tab for public playlist/album scraping without API credentials 2026-03-15 21:25:05 -07:00
spotify_worker.py Fix Album Completeness job reporting zero findings for every album 2026-04-24 12:39:41 -07:00
tag_writer.py Separate AcoustID file logging 2026-04-21 18:00:31 +03:00
tidal_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
tidal_download_client.py Fix Tidal device-auth link opening SoulSync instead of link.tidal.com 2026-04-24 14:27:17 -07:00
tidal_worker.py fix: stop enrichment workers from re-processing rows forever 2026-04-19 15:22:24 -07:00
watchlist_scanner.py Move the import flows and related post-processing pipelines into separate modules 2026-04-27 19:54:43 +03:00
web_scan_manager.py Add SoulSync standalone library — no media server required 2026-04-17 20:34:55 -07:00
wishlist_service.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00
worker_utils.py Fix Album Completeness job reporting zero findings for every album 2026-04-24 12:39:41 -07:00
youtube_client.py Clean up 286 ruff lint errors to unblock CI and fix 10 latent bugs 2026-04-21 13:30:52 -07:00