diff --git a/personal/plans/music-artist-albumartist-repair.md b/personal/plans/music-artist-albumartist-repair.md index af1ee381..f01714cc 100755 --- a/personal/plans/music-artist-albumartist-repair.md +++ b/personal/plans/music-artist-albumartist-repair.md @@ -4,7 +4,7 @@ created: '2026-09-27' updated: '2026-09-27' type: plan namespace: personal -status: session22-add-ALBUM-ROOT-DEFECT-821-diff-blind +status: session23-ALEX-DECISION-album-always-folder-rule-4446-forgotten tags: - music - metadata @@ -21,6 +21,133 @@ related: - '[[family/how-to/navidrome-truenas-android]]' # Music `artist` + `albumartist` Repair — правила Alex и ход работ +## 🟣 СЕССИЯ 23 (2026-09-27, вечер) — ФИНАЛЬНОЕ РЕШЕНИЕ ALEX ПО `album`: «ВСЁ ЗАБЫТОЕ ДОВЕСТИ ДО ОБЩЕГО ПРАВИЛА» + +> **ТРИГГЕР:** Alex — «**Где диф последний с 371 правкой альбомов/albumartist который ты готовил?**» +> → «**Читай историю zulip сразу**» → «**Ты что там делаешь блядь?! Ты видишь чё по руки вверх +> или черный кот в той csv на 7649??**» → «**Делай чтобы все забытое соответствовало остальному +> которое уже применено.**» + +### 🔴 ГЛАВНЫЙ ФАКТ: `album` НЕ ТРОНУТ В 4446 СТРОКАХ ПЛАНА ПРИ ТОМ, ЧТО ПРОГОН 7649 «ПРОШЁЛ» + +Я запустил полный прогон 7649 (09:59–10:40 UTC, MISMATCH 0 после фикса 2 файлов НТЛ) и Navidrome +дал 837 альбомов / 0 скобок. Но Alex ткнул в `Руки вверх` и `Чёрный кот` — и там **не то**. + +**Факт по `APPLY-PLAN.csv` (7861 строка):** + +``` +album_changed 2003 +album_unchanged 5858 ← из них 4446 с непустым "чужим" значением +``` + +Разбор 5858 неизменённых по признаку «`cur_album` это имя папки/артиста или нет» +(`/tmp/st_rule5.py`): + +| Проверка `norm(cur_album)` vs | Строк | Вердикт | +|---|---:|---| +| = имя папки артиста (leaf) | 1172 | ✅ норма, не трогать | +| = имя корня-категории (root) | — | ✅ норма | +| = имя родительской папки (parent) | 99 | ✅ норма | +| = артист | 141 | ✅ норма | +| **≠ ничему из этого** | **4446** | 🔴 **ЗАБЫТОЕ** — реальный альбом из тега, правило не применено | + +### 🔴 ПРИЧИНА (та же, что в сессии 22, но теперь измерена в строках плана) + +Генератор плана делал `new_album = cur_album`, если `cur_album` непустой. Правило корня +подставлялось **только при пустом теге**. Отсюда: +- `albumartist` правится ВСЕГДА (7213 строк) → асимметрия, которую заметил Alex; +- `album` проходит транзитом (5858 строк) → 4446 из них с чужим релизом. + +**Доказательство на двух файлах Alex:** + +``` +!Retro/Тамара Миансарова/Чёрный кот.mp3 + cur_album 'Храбрый Зайчик. Песни для детей' + new_album 'Храбрый Зайчик. Песни для детей' ← НЕ ИЗМЕНЕНО (в плане, идёт в прогон 7649) + +!Pop, Club, Любэ/Руки вверх/*.mp3 + cur_album '' -> new_album 'Руки' ← имя ПАПКИ, а не артиста ('Руки Вверх') + cur_album '<чужой>' -> new_album '<чужой>' ← копия тега +``` + +### ✅ `Non spécifié` / `NULL` — ЭТО НЕ ЗАБЫТОЕ, ЭТО ИСПРАВЛЕНО (проверено в плане) + +Разница с `Храбрый Зайчик` — **`cur_album` у Benassi был мусором, и мусор-фильтр его подобрал**: + +``` +!Pop, Club, Любэ/Benassi Bros/Benny Benassi - Are You Crazy....mp3 + cur_album 'Non spécifié' -> new_album 'Benassi Bros' changed=yes ✅ +!Pop, Club, Любэ/Benassi Bros/Benny_Benassi_-_The_Night_Radio_Edit.mp3 + cur_album 'NULL' -> new_album 'Benassi Bros' changed=yes ✅ +``` + +Оба в плане и в диффе против 38-й волны. На диске применено (`TALB='Benassi Bros'`). +**Класс «забытого» = `cur_album` НЕ мусор, а валидная строка.** + +### 🔴 ПРАВИЛО, ЕДИНСТВЕННО СОДЕРЖИМОЕ В УЖЕ ПРИМЕНЁННОМ (2003 изменённых строки) + +Разбор применённых `album`-правок по отношению к пути (`/tmp/st_rule3.py`, `/tmp/st_rule4.py`): + +| Совпадение `new_album` с | Строк | +|---|---:| +| = leaf (последняя папка) | **592** | +| = leaf без `!` | **158** | +| = `new_albumartist` | 39 | +| = leaf с учётом регистра/пунктуации (`Филосовские`→`Философские`) | 16 | +| = **parent** (подпапка-диск: `К`,`L`,`1`,`disk`,`disk_v2`,`+`) | 18 папок | + +**Папок с изменённым `album` — 152, из них с несколькими разными значениями — 9.** + +**Итог правила, которое уже применено (и которое надо дотянуть на забытые):** + +| ситуация | `album` | +|---|---| +| файл в корне папки артиста | имя папки артиста | +| файл в подпапке-альбоме | имя подпапки (родительская папка файла) | +| подпапка = служебная (`disk`, `disk_v2`, `К`, `L`, `+`, `2`) | имя папки уровнем выше | +| сборник `!Retro` / `!Radio` | имя сборника без `!` (`Retro`, `Radio …`) | +| `albumartist` | по правилам D21/D27 (уже применено) | + +### ✅ РЕШЕНИЕ ALEX (дословно) + +> «**Делай чтобы все забытое соответствовало остальному которое уже применено.**» + +То есть: **`album` переопределять по правилу папки для всех 4446 забытых строк, включая те, +где в теге лежал нормальный альбом** (в т.ч. класс `ДРУГОЙ_РЕЛИЗ` 439 — это меняет прежнее +предложение «не трогать», см. сессию 22 §ОТКРЫТО → **снято**). + +⚠️ **Масштаб: правка затронет ~4446 строк плана / порядка 3000+ файлов** (не все строки +соответствуют существующим файлам — путь начинается с `/storage/Music/`). + +### 🎯 ЧТО ДЕЛАТЬ ДАЛЬШЕ (следующая сессия, по факту) + +1. Построить детектор «забытое = `new_album == cur_album` И `norm(cur_album)` ≠ leaf/parent/root/artist». +2. Написать **новый CSV** правок `album` (НЕ трогать `APPLY-PLAN.csv` без явного апрува). +3. Перегенерировать `DIFF-new-vs-38-v2.csv` → `-v3`. +4. Слить БД Navidrome (`/tmp/dump_navidrome.py`, 8167 строк) и сверить с новым CSV — где расходится. +5. Только после сверки — бэкап → apply → read-back (приёмка = перечитать теги с диска). + +### 🔴 ПИТФОЛЛ ПРОЦЕССА (зафиксирован по ходу) + +- 🔴 **Alex прерывает инлайн-скрипты.** `execute_code` и `python3 - <<'EOF'` — ЗАПРЕЩЕНЫ. + Только `write_file` → `python3 /tmp/x.py`. Подтверждено репликой: «**Хватит инлайнить!!!**» +- 🔴 **Путать «запись диффа» и «строку плана» нельзя.** 2003 применённых записей `album` против + 4446 забытых строк плана — разные базы счёта (ср. §Число 371 ≠ строки диффа). +- 🔴 **`grep` по CSV даёт 0** на `,yes$` — считать только `csv.DictReader` (повтор W-правила). +- 🔴 **`execute_code` падает на `No module named 'psutil'`** в этом окружении — использовать + терминал с файловым скриптом. + +### 🛠 СКРИПТЫ ДИАГНОСТИКИ ЭТОЙ СЕССИИ + +| Скрипт | Что считает | +|---|---| +| `/tmp/st_album.py` | total rows / album changed vs unchanged / классы | +| `/tmp/st_rule.py`, `/tmp/st_rule2.py`, `/tmp/st_rule3.py` | совпадение `new_album` с leaf/root/aa/artist | +| `/tmp/st_rule4.py` | папок с изменённым `album`, поиск `==PARENT` и `OTHER` | +| `/tmp/st_rule5.py` | 🔴 **главный**: разбор 5858 неизменённых → 4446 ЗАБЫТЫХ | + +--- + ## 🟣 СЕССИЯ 18-ДОП (2026-09-27, вечер) — ИНВЕНТАРЬ ДИФФА ПО ФАКТУ, ПОСЛЕ ВОПРОСА ALEX «ГДЕ ДИФ?» > **Триггер:** Alex — «**Где диф последний с 371 правкой альбомов/albumartist который ты готовил?**»