[2026-09-27] eagle: personal/plans/music-artist-albumartist-repair.md personal/plans/tagwriter-container.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-27 17:46:47 +06:00
1 parent 0bc365a079
commit d520e6331d
2 files changed
+173 -17

No files matched your search

+111 -16
View File
@@ -19,22 +19,25 @@ related:
- '[[personal/tech/music-tags-repair-truenas]]'
- '[[personal/plans/tagwriter-container]]'
- '[[family/how-to/navidrome-truenas-android]]'
status: session18-album-306-fixed-new-diff-generated
status: session18-complete-waiting-apply-step2
# Music `artist` + `albumartist` Repair — правила Alex и ход работ
## 🟣 СЕССИЯ 18 (2026-09-27) — NAVIDROME РАЗВЁРНУТ, ДЕФЕКТ-КЛАСС ВСКРЫТ, ПРАВИЛА ВОССТАНОВЛЕНЫ ИЗ ZULIP, 306 СТРОК ИСПРАВЛЕНЫ, НОВЫЙ ДИФФ ГОТОВ
> **СТАТУС СЕССИИ 18 (финал):** Navidrome ✅ развёрнут и работает (см. ниже +
> **СТАТУС СЕССИИ 18 (ФИНАЛ):** Navidrome ✅ развёрнут и работает (см. ниже +
> `[[family/how-to/navidrome-truenas-android]]`). Дефект-класс `new_album == cur_album`
> вскрыт (6202 строки, 79%), реального мусора **9 папок / 265 треков→306 строк**.
> Правила `album` восстановлены из базы Zulip. **306 строк исправлены в `APPLY-PLAN.csv`**,
> затем **ещё 58 строк по 3 дефектам** (склейка артист+год 18, чужой `albumartist` 7,
> `album`=название песни 33). Итог по файлу: **скобок 0, `albumartist`-разброс 7→2 папки,
> `Green Apelsin` 13 значений→1**. Дифф `DIFF-new-vs-38-v2.csv` сгенерирован (164 album-строки),
> но ⏭ **устарел после правки 58 строк — требует перегенерации**.
> ⚠️ Открыто: 2 папки с разным `albumartist` (`Ленинград`/`Сергей Шнуров`; `ВИА МЕА`),
> вычитка диффа Alex, валидатор смысла.
> См. §ПРАВКА 3 ДЕФЕКТОВ, §КАЛИБРОВКА ДЕТЕКТОРОВ, §СДЕЛАНО: правка 306 строк, §НОВЫЙ ДИФФ.
> `album`=название песни 33), затем **+12** (`Шнуров`→`Ленинград` 1, `NONSONS - zvezda`→`zvezda` 11).
> **Всего 371 строка. Проверено по файлу: скобок 0, `albumartist`-разброс 7→1 папка,
> `Green Apelsin` 13→1 значение.**
> ✅ Дифф **`DIFF-new-vs-38-v2.csv` ПЕРЕГЕНЕРИРОВАН** (164 album-строки, +12), полнота проверена —
> все 18 целевых `album` и 6 `albumartist` внутри. Старый дифф **не тронут**.
> Alex дал команду **«применяй»** → **ШАГ 1 (сверка артефактов) ПРОЙДЕН**: найдено 2 расхождения
> (скрипт на NAS и план на NAS — оба старые). ⏭ **ШАГ 2 не начат — ждёт «шаг 2» от Alex.**
> См. §ПРАВКА 3 ДЕФЕКТОВ, §КАЛИБРОВКА ДЕТЕКТОРОВ, §СДЕЛАНО: правка 306 строк, §НОВЫЙ ДИФФ,
> §СВЕРКА АРТЕФАКТОВ ШАГ 1.
> **Контекст:** Navidrome поднят и просканировал библиотеку (8043 трека). Alex открыл UI и
> спросил: «**Откуда альбомы в скобках взялись?** Типа `Дискотека Авария` — для корня,
@@ -459,19 +462,88 @@ new_album начинается со скобки: 306 → 0
Green Apelsin: album значений 13 → 1 ('Северный ветер')
```
### ⚠️ ОСТАЛОСЬ 2 ПАПКИ С РАЗНЫМ `albumartist` (ждут решения Alex)
### ✅ ОБА ВОПРОСА ЗАКРЫТЫ ALEX (2026-09-27, конец сессии 18)
| Папка | Значения | Вопрос |
Alex: «**Шнурова править. `Другое..` — нет. Альбом должен быть `zvezda`**».
| Папка | Решение Alex | Сделано |
|---|---|---|
| `z Другое.../Ленинград` | `Ленинград` ×4, **`Сергей Шнуров`** ×1 | ставить `Ленинград`? |
| `z Другое.../Enigma.../Ленинград` (корень) | **`ВИА МЕА`** ×1, `Красная Плесень` ×2 | что с `ВИА МЕА`? |
| `z Другое.../Ленинград` | `Сергей Шнуров` → **`Ленинград`** | ✅ 1 строка |
| `z Другое, Enigma, Ленинград` (корень) | **НЕ трогать** (разные артисты — легитимно) | — |
| `!Rock&Folk/NONSONS - zvezda` | `album` = **`zvezda`** (не `NONSONS - zvezda`) | ✅ 11 строк |
**Также осталось:** 11 «склеек» — **ложные** (`NONSONS - zvezda` = имя папки артиста, верно).
Скрипт `/tmp/fix_shnur_zvezda.py`, бэкап
`APPLY-PLAN.csv.bak-before-shnur-zvezda-20260927-174058`.
### ⏭ НЕ СДЕЛАНО: перегенерация диффа после правки 3 дефектов
**Проверка фактом после правки:**
```
Ленинград: albumartist={'Ленинград'}
NONSONS - zvezda: album={'zvezda'}
Папок с РАЗНЫМИ albumartist: 1 (только z Другое корень — по решению Alex)
```
`DIFF-new-vs-38-v2.csv` сгенерирован **ДО** правки 58 строк. **План изменился — дифф устарел,
требует перегенерации** (`python3 ~/Downloads/music-tags/diff_new_vs_38_v2.py`).
> 🔑 `NONSONS - zvezda` — **имя папки артиста**, а `album` должен быть `zvezda`: правило
> «в корне группы `album` = имя папки артиста» НЕ отменяет правило Alex «имя папки и склейка
> `Родитель - Папка` в `album` ЗАПРЕЩЕНЫ». Для этой папки правильное значение — чистый альбом.
### ✅ ПЕРЕГЕНЕРАЦИЯ ДИФФА ВЫПОЛНЕНА
`DIFF-new-vs-38-v2.csv` перегенерирован ПОСЛЕ всех правок (306 + 58 + 12).
| | album-строк |
|---|---:|
| Старый `DIFF-new-vs-38.csv` | 152 (101 ПАПКА + 51 ТРЕК) |
| **Новый `DIFF-new-vs-38-v2.csv`** | **164 (112 ПАПКА + 52 ТРЕК)** |
**Проверка полноты (`/tmp/final_verify.py`):** все **18** целевых значений `album` найдены
в новом диффе, все **6** целевых `albumartist` найдены. `Не найдено: нет`.
Схлопывание сработало: 306 построчных правок → **15 записей по папкам** (значение одинаково
у всех файлов папки — правило 2 диффа).
**MD5:** старый `4e073fe50c191cc50015d3f15f6a6d28` (mtime 15:46 — **НЕ ТРОНУТ**),
новый `7bc222a1087787c390026d624af932f3`.
### 🔴 КОМАНДА ALEX «ПРИМЕНЯЙ» → GATE: ШАГ 1 (СВЕРКА АРТЕФАКТОВ) ПРОЙДЕН, ШАГ 2 НЕ НАЧАТ
Alex: «**Отлично, применяй**». Прогон **НЕ запущен** — сначала сверка артефактов на NAS
(прогон необратим, меняет 7861 mp3).
**Результат сверки (шаг 1, факты):**
| Артефакт | MD5 / состояние | Вердикт |
|---|---|---|
| Скрипт на Mac (`~/Automation` = `~/Downloads/tagwriter`) | `c7a2bc143e38820f2050310cbe01b799` | ✅ эталон |
| **Скрипт в образе `tagwriter:latest`** | `c7a2bc143e38820f2050310cbe01b799` | ✅ **совпал** |
| **Скрипт на NAS** `/mnt/RED_2TB/docker/arr/tagwriter/` | `c8083f9760a424d453b34f646556c1ea` | 🔴 **расходится** |
| `ENTRYPOINT`/`CMD`/`USER` в `latest` | `["python3","/app/apply_tags_v2.py"]` / `["--dry-run"]` / `950:950` | ✅ фиксы на месте |
| **План на NAS** `apply-plan.csv` | `245efb55ab1de26cb5172f0754192c3d` | 🔴 **СТАРЫЙ** (без 371 правки) |
| Бэкап `Music/backup` | 50 ГБ | ✅ есть (без него `cmd_apply()` → `exit 2`) |
| `tagwriter:v2` | `e5e2437a2fda90cb6b06d6daa6330cb` | ⚠️ старая версия — **не использовать** |
| uid образа `latest` | `uid=950 gid=950 groups=950` | ✅ `USER 950:950` работает |
> 🔴 **ПИТФОЛЛ: `Dockerfile.v2` на Mac — УСТАРЕВШАЯ СПРАВОЧНАЯ КОПИЯ.**
> В нём НЕТ `ENTRYPOINT` и `USER 950:950`, хотя в доке они описаны как фиксы. **Боевой образ
> `tagwriter:latest` собран с фиксами** (проверено `docker inspect` + `id` внутри контейнера).
> **Не пересобирать из этого файла — потеряешь фиксы.** Файл на Mac:
> ```
> FROM python:3.11-slim
> RUN pip install --no-cache-dir mutagen==1.47.0
> WORKDIR /app
> COPY apply_tags_v2.py /app/apply_tags_v2.py
> CMD ["python3", "/app/apply_tags_v2.py", "--dry-run"] ← нет ENTRYPOINT, нет USER
> ```
### ⏭ ШАГ 2 (НЕ ВЫПОЛНЕН — ждёт «шаг 2» от Alex)
1. `docker cp` актуального `apply_tags_v2.py` (Mac) → контейнер `/app/apply_tags_v2.py`
2. Залить актуальный `APPLY-PLAN.csv` (Mac) → NAS `/mnt/RED_2TB/docker/arr/tagwriter/apply-plan.csv`
3. Сверить MD5 обоих на NAS после заливки
4. `--dry-run` → сверить счётчики
5. **Только после «go»** — `--apply --verify`
> 🔴 **Правило шага 1:** **перед необратимым прогоном сверять MD5 скрипта (Mac / образ / NAS)
> и плана (Mac / NAS).** В этой сессии расхождения нашлись в ДВУХ местах из двух проверенных —
> без сверки прогон пошёл бы **по старому плану без 371 правки**.
### ✅ Артефакты сессии 18
@@ -500,6 +572,29 @@ Green Apelsin: album значений 13 → 1 ('Северный вет
| `/tmp/check_diff_coverage.py` | проверка покрытия дефекта диффом (7,6%) |
| `/tmp/where_avaria.py` | где физически лежат файлы `(Авария)` |
| `/tmp/album_rules_v2.py` | применение финальных правил (КОРЕНЬ/ПОДПАПКА/СБОРНИК) |
| `/tmp/fix_shnur_zvezda.py` | ✅ **правка 12 строк** (`Шнуров`→`Ленинград`, `NONSONS - zvezda`→`zvezda`) |
| `APPLY-PLAN.csv.bak-before-shnur-zvezda-20260927-174058` | бэкап плана до этой правки |
| `/tmp/final_verify.py` | ✅ проверка перегенерированного диффа (18 album + 6 albumartist найдены) |
| `/tmp/verify_new_diff.py` | сравнение album-строк старого/нового диффа (152→164) |
### 📊 ИТОГ СЕССИИ 18 — 4 волны правок `APPLY-PLAN.csv`
| Волна | Строк | Скрипт | Бэкап |
|---|---:|---|---|
| Скобочный мусор в `album` | 306 | `/tmp/fix_album_306.py` | `.bak-before-album-305fix-20260927-173213` |
| 3 дефекта (склейка/чужой aa/название песни) | 58 | `/tmp/fix_3defects.py` | `.bak-before-3defects-20260927-173855` |
| Шнуров + `zvezda` | 12 | `/tmp/fix_shnur_zvezda.py` | `.bak-before-shnur-zvezda-20260927-174058` |
| **ИТОГО** | **371** | | 3 бэкапа |
**ФИНАЛЬНЫЕ ПРОВЕРКИ ПО ФАЙЛУ (не по коду):**
```
new_album начинается со скобки: 0
Папок с РАЗНЫМИ new_albumartist: 1 (z Другое корень — решение Alex «не трогать»)
Green Apelsin: album значений 1 ('Северный ветер')
Целевые значения в DIFF-new-vs-38-v2.csv: 18/18 album, 6/6 albumartist
album-строк: старый 152 → новый 164 (+12)
Старый DIFF-new-vs-38.csv: md5 4e073fe5… НЕ ТРОНУТ (mtime 15:46)
```
| `/tmp/verify_new_diff.py` | проверка попадания 15 групп в новый дифф |
---
+62 -1
View File
@@ -549,7 +549,68 @@ FIELD_ORDER = sorted({"title", "artist", "albumartist", "album", "genre", "track
```
**Правило: сортировка по `field` = по алфавиту, а не по логической важности.**
### 🔴 ОТКРЫТЫЙ ДЕФЕКТ: `!Rock&Folk/Rammstein/misc`
### ✅ ЗАКРЫТО (сессия 18): `!Rock&Folk/Rammstein/misc` — дефекта НЕТ
Alex: «**Что блядь с рамшьайно не закрыто? Какой нахуй Puhdys?! Мы меняли на misc album!**»
**Проверка фактом по `APPLY-PLAN.csv` (135 строк Rammstein):**
```
!Rock&Folk/Rammstein/misc → album='misc', albumartist='Rammstein' ✅ (3 файла)
```
`Puhdys` встречается **ровно 1 раз и корректно**: в `artist` файла
`misc/Puhdys - Wut Will Nicht Sterben.mp3` (`albumartist='Rammstein'`, `album='Wilder Freiden'`) —
песня реально исполнена Puhdys, альбом принадлежит Rammstein. **Дефекта `album='Rammstein'` /
`albumartist='Puhdys'` в плане НЕТ — это был снимок ДО правок.**
| Было (эта дока, до правок) | Сейчас (факт по файлу) |
|---|---|
| `album '' → 'Rammstein'` ❌ | `album='misc'` ✅ |
| `albumartist → 'Puhdys'` ❌ | `albumartist='Rammstein'` ✅ |
Все 135 строк Rammstein проверены: `albumartist='Rammstein'` везде, альбомы корректные
(`Sehnsucht`, `Rosenrot`, `Herzeleid`, `Engel [Fan Edition]`, `Lost Highway`, `Du Hast`,
`Sehnsucht [Japan]`). **Открытых дефектов по Rammstein нет.**
### 🔴 ПИТФОЛЛ: `Dockerfile.v2` на Mac — УСТАРЕВШАЯ СПРАВОЧНАЯ КОПИЯ
Проверено в сессии 18. Файл `~/Automation/music-tags/Dockerfile.v2` содержит:
```dockerfile
FROM python:3.11-slim
RUN pip install --no-cache-dir mutagen==1.47.0
WORKDIR /app
COPY apply_tags_v2.py /app/apply_tags_v2.py
CMD ["python3", "/app/apply_tags_v2.py", "--dry-run"] ← НЕТ ENTRYPOINT, НЕТ USER 950:950
```
**Фиксов дефектов 1 и 2 в нём НЕТ**, хотя выше в §«ДВА ДЕФЕКТА `Dockerfile.v2`» они описаны.
**Боевой образ `tagwriter:latest` собран С фиксами** — проверено фактом:
```
docker inspect tagwriter:latest --format '{{json .Config.Entrypoint}} | {{json .Config.Cmd}} | USER={{.Config.User}}'
→ ["python3","/app/apply_tags_v2.py"] | ["--dry-run"] | USER=950:950
docker run --rm --entrypoint sh tagwriter:latest -c 'id' → uid=950 gid=950 groups=950
```
🔴 **НЕ пересобирать образ из `Dockerfile.v2` на Mac — потеряешь `ENTRYPOINT` и `USER 950:950`.**
### ✅ СВЕРКА АРТЕФАКТОВ ПЕРЕД ПРОГОНОМ (сессия 18, шаг 1) — 2 РАСХОЖДЕНИЯ ИЗ 2
Alex: «**Отлично, применяй**» → прогон **не запущен**, сначала сверка (прогон необратим).
| Артефакт | MD5 | Вердикт |
|---|---|---|
| Скрипт Mac (`~/Automation` = `~/Downloads/tagwriter`) | `c7a2bc143e38820f2050310cbe01b799` | ✅ эталон |
| Скрипт в образе `tagwriter:latest` | `c7a2bc143e38820f2050310cbe01b799` | ✅ совпал |
| **Скрипт на NAS** `/mnt/RED_2TB/docker/arr/tagwriter/` | `c8083f9760a424d453b34f646556c1ea` | 🔴 **расходится** |
| **План на NAS** `apply-plan.csv` | `245efb55ab1de26cb5172f0754192c3d` | 🔴 **СТАРЫЙ** |
| Бэкап `Music/backup` | 50 ГБ | ✅ есть |
| `tagwriter:v2` | `e5e2437a2fda90cb6b06d6daa6330cb` | ⚠️ старая — не использовать |
> 🔴 **Правило: перед необратимым прогоном сверять MD5 скрипта (Mac / образ / NAS) и плана
> (Mac / NAS).** Здесь расхождения нашлись в **обоих** проверенных местах — без сверки прогон
> пошёл бы по **старому плану без 371 правки** (сессия 18 внесла 371 изменение).
**Шаг 2 (не выполнен, ждёт Alex):** `docker cp` скрипта + заливка актуального плана → MD5-сверка →
`--dry-run` → `--apply --verify` только после «go».
### 🔴 ОТКРЫТЫЙ ДЕФЕКТ (требует проверки): `!Rock&Folk/Rammstein/misc`
Alex: «**`!Rock&Folk/Rammstein/misc` - album - rammstein - неправильно**».