Strip non-timestamp characters (BOM, invisible chars) from date/year values
both when reading existing tags in metadata_resolver and when writing in
executor. Also harden the EasyID3 except block to not wipe existing tags
when adding a missing ID3 header, and add per-field try/except in MP3 tag
writing so one bad field doesn't abort the entire track.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
scanner: nicht in Unterordner wenn Root Audio-Dateien enthält (verhindert
Doppel-Scan bei versehentlichen Unterordner-Kopien); nur Disc-Ordner
(CD1, Disc 2…) werden bei Multi-CD-Alben rekursiert.
hint_extractor: M3U/Playlist-Dateien als Track-Reihenfolge-Quelle; BOM-
Bereinigung; Tracklist-Matching auch per Titel (nicht nur per Nummer);
tracknumber=0 wird als 'keine Nummer' gewertet.
metadata_resolver: sequenzielle Fallback-Nummerierung (1,2,3…) für Tracks
ohne Tracknummer — verhindert '00'-Präfix beim --rename; dir_artist hat
Vorrang vor 'Various Artists'-Heuristik; LLM darf bei Konfidenz <0.3
auch bestehende Werte korrigieren (Tippfehler im Verzeichnisnamen).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_claude_resolve() nutzt jetzt Ollama lokal (kostenlos, RTX 3090) als
erste Wahl, dann OpenRouter/DeepSeek V3 (sehr günstig) und zuletzt
Claude API. Neue ENV-Variablen: OPENROUTER_API_KEY, OLLAMA_RESOLVE_MODEL.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AI-powered per-album pipeline: scan → local hints → MusicBrainz/Discogs/Claude
resolve → cover art → interactive or auto review → tag write + rename + report.
All external dependencies optional; 17/17 unit tests passing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>