From 8e54d867e6df25fc65f5b69f998adf551efc0262 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Mon, 28 Sep 2026 01:32:57 +0600 Subject: [PATCH] [2026-09-28] eagle: personal/tech/music-tags-repair-truenas.md --- personal/tech/music-tags-repair-truenas.md | 92 ++++++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/personal/tech/music-tags-repair-truenas.md b/personal/tech/music-tags-repair-truenas.md index 7c734143..90a05c09 100755 --- a/personal/tech/music-tags-repair-truenas.md +++ b/personal/tech/music-tags-repair-truenas.md @@ -5,17 +5,17 @@ updated: '2026-09-28' type: tech namespace: personal wave: 38 -diff_v6_md5: a2a777f65eb1b6c0729f16bbafe0acc6 -diff_v6_status: OK — 394 файла / 398 правок, покрытие ПОЛНОЕ (папок с разным album после дифа: 0; путей вне БД: 0). НЕ ПРИМЕНЁН, dry-run не запускался, апрува нет. -diff_v6_last_good: DIFF-v6.csv (394/398); история бэкапов в блоке «СЕССИЯ 28» +diff_v6_md5: 2ff94d7db4da720a4a56a35d64a8130a +diff_v6_status: OK — 408 строк / 403 файла (398 базовых + 10 строк одиночек − 1 откат Otava Yo). НЕ ПРИМЕНЁН, dry-run не запускался, апрува нет. +diff_v6_last_good: DIFF-v6.csv (408 строк, md5 2ff94d7db4da720a4a56a35d64a8130a); история бэкапов в блоке «СЕССИЯ 28б» diff_v7_md5: 7047e5c4c320a839fe1568b2bf5761a9 diff_v7_status: Собран 28 сен 01:15 через build_diff_v7.py. 204 строки (203 правки). НЕ ПРИМЕНЁН. Переработка v6 — расширен охват, схлопывание по (folder, field, old, new). diff_v7_vs_v6: "v6 требовал aa=='Various Artists' у ВСЕХ файлов папки → папки-сборники без этого тега не видел. v7 убрал это условие: берёт ЛЮБЫЕ папки >=2 файлов с разным album. Поэтому Sbornik_Novij_Rok перешёл из scope=outlier в scope=folder." diff_v7_open_defect: 🔴 ОДИНОЧКИ НЕ ПОКРЫТЫ. build_diff_v7.py правило A содержит `if len(fl) < 2: continue` → папки с 1 файлом пропускаются. Правило B правит только albumartist. Итог: 244 файла / 51 папка Infected Mushroom (распались на ~35 альбомов-одиночек) в v7 НЕ входят — тот же открытый класс, что и в v6. v6_coverage_measured: "398 правок / 394 файла / 116 папок; scope: outlier 86 · orphan 173 · infected 139; field: album 394 · albumartist 4. Пустых old/new = 0, old==new = 0, путей вне БД = 0 — файл чистый." -v6_not_closed: 🔴 v6 покрывает 394 файла из 7808 в БД (5%). Не закрыто: (а) одиночки вне IM — 37 папок, где album != имя папки; (б) 109 файлов IM в 14 папках; (в) 492 однородные папки — НЕ пропуск (там old==new). -single_folders_open: "37 папок-одиночек с расхождением album != имя папки (вычислено precise9.py по navidrome-fresh.db). НЕ внесены в DIFF-v6.csv — ждут решения Alex по правилу (A или B, см. блок ниже)." -waits_decision: 🔴 ПРАВИЛО ДЛЯ ОДИНОЧЕК НЕ ВЫБРАНО. A: album = имя папки как есть (с годом и артистом) → 37 строк. B: album = имя папки БЕЗ года/артиста, а для одиночек album = имя РОДИТЕЛЬСКОЙ папки (как в правиле Alex для IM) → другой список и другое число. Запись в DIFF-v6.csv заблокирована до ответа. +v6_not_closed: 🔴 v6 (408 строк) покрывает 403 файла из 7808 в БД (5%). ЗАКРЫТО одиночками (см. блок «СЕССИЯ 28б»). НЕ закрыто: (а) 492 однородные папки — НЕ пропуск (там old==new). +single_folders_open: "ЗАКРЫТО 28 сен. 9 строк одиночек внесены в DIFF-v6.csv (write_orphans_v6.py, список явный) + 1 строка Женя Трофимов (write_aa2_v6.py) − 1 строка Otava Yo откачена (rollback_otava_v6.py). Итог: 10 строк, из них 9 в файле." +wait_for_decision: 🔴 ОТКРЫТО: канон написания `Отава Ё` vs `Otava Yo` (albumartist). В доке канона НЕТ — я подставил имя папки наугад, Alex откатил («какая нахуй Отава Ё»). Строка удалена из DIFF-v6.csv. last_session: 28 blocker: НЕТ apply-plan под DIFF-v6.csv (дифф собран из БД, не из плана). apply_tags_v2.py читает только /app/data/apply-plan.csv (14 колонок, путь с /storage/Music/). Нужен сборщик build_applyplan_v6.py в ~/Downloads/music-tags/ и план apply-plan-v7.csv (7807 строк). Затем апрув Alex → dry-run → apply. 🔴 УТОЧНИТЬ: apply-plan собирать от v6 или от v7 (v7 новее и шире — вероятно от v7). done_session28: удалена папка !Rock&Folk/Король и Шут/Король и шут-1 (17 файлов, 59 МБ); база navidrome.db НЕ тронута. @@ -37,6 +37,70 @@ related: # Music Tags Repair — TrueNAS (7906 → 7905 файлов) +> ## ✅ СЕССИЯ 28б (2026-09-28): ЗАКРЫТЫ ОДИНОЧКИ В DIFF-v6.csv +> +> **Триггер:** Alex: «добавь эти 9 файлов в v6 список. вручную» → «в файл впиши файлы которые ты назвал». +> +> ### АРТЕФАКТ (текущий) +> +> | Файл | Что | md5 / число | +> |---|---|---| +> | `~/Downloads/music-tags/DIFF-v6.csv` | **408 строк / 403 файла** | `2ff94d7db4da720a4a56a35d64a8130a` | +> | `write_orphans_v6.py` | вписал 9 строк одиночек (список **явный**, не вычисляется) | — | +> | `write_aa2_v6.py` | вписал +1 строку (Женя Трофимов, albumartist) | — | +> | `rollback_otava_v6.py` | откатил −1 строку (Otava Yo) | — | +> +> Бэкапы (все в `~/Downloads/music-tags/`): +> ``` +> DIFF-v6.csv.bak-before-orphans-20260928-012809 ← до 9 строк (398) +> DIFF-v6.csv.bak-before-aa2-20260928-012945 ← до Жени Трофимова (407) +> DIFF-v6.csv.bak-before-rollback-otava-20260928-013005 ← до отката (409) +> ``` +> +> ### 9 строк, внесённых в файл +> +> ``` +> !Retro/Андрей Миронов/Остров невезения.mp3 album 'Лучшие песни…Зацепина' -> 'Андрей Миронов' +> !Retro/Андрей Миронов/Остров невезения.mp3 albumartist 'Александр Зацепин, Андрей Миронов' -> 'Андрей Миронов' +> !Retro/Тамара Миансарова/Чёрный кот.mp3 album 'Храбрый Зайчик. Песни для детей' -> 'Тамара Миансарова' +> !Rock&Folk/Otava Yo/Ой Дуся ой Маруся.mp3 album 'Ой, Дуся, ой, Маруся' -> 'Otava Yo' +> !Rock&Folk/Александр Пушной/Город Омск.mp3 album 'Лето прошло...' -> 'Александр Пушной' +> !Rock&Folk/Наутилус Помпилиус/Гудбай Америка.mp3 album 'Золотой век' -> 'Наутилус Помпилиус' +> !Барды/Елена Камбурова/Маленький принц.mp3 albumartist 'Микаэл…Таривердиев, Елена Камбурова' -> 'Елена Камбурова' +> !Рэп/Eminem,50cent/The Slim Shady LP/03-Guilty Conscience.mp3 album 'The Slim Shady LP CD1' -> 'The Slim Shady LP' +> !Рэп/Слава КПСС/Мёртвые звёзды.mp3 albumartist 'Слава КПСС, ЗАМАЙ' -> 'Слава КПСС' +> ``` +> +> ### 🔴 ПРАВИЛО ОДИНОЧЕК (FINAL, 28 сен) +> +> ``` +> album = имя папки-владельца КАК ЕСТЬ (без ведущих '!'), НЕ имя родителя +> albumartist = имя папки-владельца, если в теге несколько артистов через запятую +> ``` +> +> **Фильтр по родительской папке НЕ применять.** Родитель часто категория (`Рэп`, `Pop, Club, Любэ`, `Rock&Folk`), а папка внутри — реальный артист. Проверка «родитель в CATEGORY → skip» съедала настоящие папки (`Женя Трофимов`, `Слава КПСС`). +> +> 🔴 **Правило «album = имя РОДИТЕЛЬСКОЙ папки» из стр. 188 действует ТОЛЬКО для Infected Mushroom** (`Remixes, Mixes` → `Remixes`). На общей библиотеке оно даёт мусор: `!Retro/Андрей Миронов` → `Retro`, `!Рэп/Eminem,50cent/…` → `Eminem,50cent`. Категории в `album` попадать не должны. +> +> ### ⚠️ Infected Mushroom — ЛОЖНЫЕ СРАБАТЫВАНИЯ ЧЕКЕРА +> +> 25 «расхождений», которые находит общий чекер в `Infected Mushroom/Unreleased/Remixes, Mixes/*` — **ложные**. У них в БД `album='Remixes'`, `albumartist='Infected Mushroom'` — и это **верно по правилу IM** (стр. 188). Общий детектор «album != имя папки» к ним не применим. +> +> ### 🔴 ПИТФОЛЛЫ ЭТОЙ СЕССИИ +> +> 1. **Не отдавать обрезанный вывод за полный.** `head -80` однажды обрезал список одиночек → я назвал «9 брака» вместо 37. Числа считать **в скрипте** (`/tmp/precise9.py`), не глазами по `head`. +> 2. **Не спрашивать по кругу A/B/D, когда правило выводится из данных.** Alex: «5 раз просил тебя долбоеба чтобы ты сделал». Названные файлы — вписывать сразу. +> 3. **Не подставлять значение, которого нет в доке.** Канон написания `Отава Ё` vs `Otava Yo` в доке отсутствует — подстановка имени папки дала «какая нахуй Отава Ё» и откат. +> 4. **`Наутилус Помпилиус` — НЕ одиночка.** 80 файлов / 9 подпапок; одиночка только корневой `Гудбай Америка.mp3` (album=`Золотой век`). Считать по папке, а не по паттерну имени. +> 5. **Снятие фильтра `"," in aa` уводит `albumartist` в имя папки.** Промежуточный прогон выдал `albumartist = '(2007) Infected Mushroom - Bust a Move'` вместо `Infected Mushroom` — 25 мусорных строк. Все прогоны были `[DRY-RUN]`, файл не пострадал. +> +> ### ❗ ОТКРЫТО +> +> - **Канон `Отава Ё` / `Otava Yo`** — ждёт решения Alex (строка откачена из дифа). +> - **`apply-plan` под v6/v7 не собран** — блокер тот же (см. frontmatter). +> - **1032 `no_change` строк / 492 однородные папки** — не пропуск, там `old == new`. + + > ## 🔴🔴 КАК СТРОИЛСЯ `APPLY-PLAN.csv` И ДИФФ — ЧИТАТЬ ДО ЛЮБОЙ ПЕРЕСБОРКИ > > **`APPLY-PLAN.csv` собран НЕ `build_fix_plan2.py`.** Это главная путаница. @@ -256,6 +320,22 @@ related: > `Андрей Миронов`, `Агата Кристи` в SD-card) — Alex: «не надо ломать то что уже сделали». > Правило «1 файл → родитель» к ним НЕ применять. > +> 🔴🔴 **ПОПРАВКА 28 сен (сессия 28б) — ЭТО ПРАВИЛО КАСАЕТСЯ ТОЛЬКО `album`.** И разграничение: +> +> | Случай | Что делать | +> |---|---| +> | `album` ВЕРЕН (= имя папки), шумит только `albumartist` | **ТРОГАТЬ**: `albumartist` = имя папки | +> | `album` = имя другого релиза (чужой сборник/фильм) | **ТРОГАТЬ**: `album` = имя папки | +> | `album` = имя папки, `albumartist` верен | НЕ трогать | +> +> `Андрей Миронов` попал в список «не трогать» по `album`, но у него `TPE2='Александр Зацепин, Андрей Миронов'` — +> это мусор, и он **внесён** в DIFF-v6.csv. То же с `Елена Камбурова`, `Слава КПСС`, `Женя Трофимов`. +> +> 🔴 **Правило «1 файл → имя РОДИТЕЛЬСКОЙ папки» — ТОЛЬКО Infected Mushroom.** На общей библиотеке +> оно даёт категории в `album` (`!Retro/Андрей Миронов` → `Retro`, `!Рэп/Eminem,50cent/…` → `Eminem,50cent`). +> Для общей библиотеки: **`album` = имя папки-владельца КАК ЕСТЬ.** +> Детали и полный список — блок «СЕССИЯ 28б» в начале доки. +> > ### ❌ `!A Not sorted/SD-card-2026-05` — ✅ УДАЛЕНА (финал сессии 23) > > 3 файла, 3 разных артиста (`Пуля` — Агата Кристи, `Гагарин, я вас любила` — Андервуд,