[2026-09-27] eagle: personal/plans/music-artist-albumartist-repair.md personal/tech/music-tags-repair-truenas.md
This commit is contained in:
1 parent
7932f70274
commit
68356f1677
2 files changed
+166
-20
No files matched your search
@@ -4,7 +4,7 @@ created: '2026-09-27'
|
||||
updated: '2026-09-27'
|
||||
type: plan
|
||||
namespace: personal
|
||||
status: v3-verified-3-discrepancies / dry-run-blocked-on-alex-decision
|
||||
status: dry-run-done / boevoy-zapusk-pravilnyy-cmd-ne-podtverzhden
|
||||
tags:
|
||||
- music
|
||||
- metadata
|
||||
@@ -46,12 +46,17 @@ related:
|
||||
Канон: ~/Downloads/music-tags/APPLY-PLAN.csv (7861 строка — НЕ ПЕРЕЗАПИСЫВАТЬ)
|
||||
```
|
||||
|
||||
**Состояние:** артефакты v3 проверифицированы 27 сен. **Dry-run НЕ запущен** —
|
||||
блокирует решение Alex: дифф считает группы (genre 911), dry-run считает файлы
|
||||
(genre 4359). См. § ВЕРИФИКАЦИЯ v3.
|
||||
**Состояние (27 сен, сессия ~30):** ✅ **dry-run ВЫПОЛНЕН УСПЕШНО** — `7653 к правке`,
|
||||
`mp3 на диске 7861`, `не найдено 0`. Требование Alex «совпасть по цифрам с
|
||||
APPLY-PLAN-v3-changes» **снято самим Alex** («нихуя не понял… очевидно что полный набор»):
|
||||
дифф считает группы, dry-run — файлы, совпадение недостижимо by design. Решение Alex:
|
||||
**пишем полный набор полей** (не только `TCON`).
|
||||
|
||||
**Открытый дефект:** жанры (`TCON`) не записаны в теги — прогон шёл старым скриптом.
|
||||
Скрипт уже исправлен, **прогон не сделан**.
|
||||
🔴 **БОЕВОЙ ПРОГОН НЕ СОСТОЯЛСЯ — запущен с неверным аргументом.** См. § БОЕВОЙ ПРОГОН,
|
||||
немедленно читать перед повтором.
|
||||
|
||||
**Открытый дефект:** жанры (`TCON`) в тегах отсутствуют. Скрипт исправлен, dry-run доказал,
|
||||
что `TCON` пишется. Боевой прогон — ждёт корректной команды.
|
||||
|
||||
**Доступ к NAS:** `ssh -i ~/.ssh/id_rsa truenas_admin@mallexxx.duckdns.org`
|
||||
⚠️ `192.168.1.100` — ЧУЖАЯ подсеть, не использовать. Подробнее → [[family/how-to/truenas-access]]
|
||||
@@ -71,6 +76,8 @@ related:
|
||||
| 7 | 27 сен | `.ndignore` — 6 бэкапов исключены, Navidrome их не видит | `.ndignore` |
|
||||
| 8 | 27 сен | **Канонный дифф v3 собран** — сортировка по `field`, схлопывание, шум убран | `DIFF-base-vs-applyplan-v3.csv` |
|
||||
| 9 | 27 сен | **Верификация артефактов v3 перед dry-run** — 3 расхождения вскрыты, см. § ВЕРИФИКАЦИЯ | `/tmp/verify_v3*.py` |
|
||||
| 10 | 27 сен | **Dry-run выполнен: 7653 к правке, не найдено 0** — `TCON` пишется | `/tmp/dryrun.log` |
|
||||
| 11 | 27 сен | 🔴 **Боевой прогон не состоялся** — `CMD=--dry-run` образа подставился | `/tmp/tw306/run.log` |
|
||||
|
||||
---
|
||||
|
||||
@@ -123,16 +130,33 @@ python3 /tmp/make_applyplan_v3.py
|
||||
# → /tmp/apply-plan-v3.csv
|
||||
```
|
||||
|
||||
### Применить теги (образ tagwriter)
|
||||
### Применить теги (образ tagwriter) — 🔴 ЧИТАТЬ `CMD` ОБРАЗА ПЕРЕД ЗАПУСКОМ
|
||||
```bash
|
||||
# сухой прогон
|
||||
# 1. ВСЕГДА сначала посмотреть, что в CMD образа:
|
||||
docker inspect tagwriter:latest --format 'CMD={{json .Config.Cmd}} ENTRY={{json .Config.Entrypoint}}'
|
||||
# ФАКТ 27 сен: CMD=["--dry-run"] — то есть --dry-run ПОДСТАВЛЯЕТСЯ АВТОМАТИЧЕСКИ.
|
||||
|
||||
# 2. СУХОЙ ПРОГОН — скрипт лежит в /app/, НЕ в /app/data/:
|
||||
docker rm -f twdry >/dev/null 2>&1
|
||||
docker create --name twdry --entrypoint python3 \
|
||||
-v /tmp/tw306:/app/data:ro -v /mnt/RED_2TB/storage/Music:/music:rw \
|
||||
tagwriter:latest /app/data/apply_tags_v2.py --dry-run && docker start -a twdry
|
||||
tagwriter:latest /app/apply_tags_v2.py --dry-run
|
||||
docker start -a twdry
|
||||
|
||||
# 3. БОЕВОЙ ПРОГОН — CMD переопределить явно, иначе будет dry-run (см. ПИТФОЛЛ 13):
|
||||
docker rm -f twrun >/dev/null 2>&1
|
||||
docker create --name twrun --entrypoint python3 \
|
||||
-v /tmp/tw306:/app/data:ro -v /mnt/RED_2TB/storage/Music:/music:rw \
|
||||
tagwriter:latest /app/apply_tags_v2.py --apply # ← ФЛАГ ПОДТВЕРДИТЬ В СКРИПТЕ
|
||||
docker start -a twrun
|
||||
```
|
||||
- Образ `tagwriter:latest` (НЕ `v2`), uid 950:950, amd64
|
||||
- План читается ТОЛЬКО как `/app/data/apply-plan.csv`
|
||||
- Скрипт: `/app/apply_tags_v2.py` — пишет `TIT2 TPE1 TPE2 TALB TCON TRCK`
|
||||
- Образ `tagwriter:latest` (НЕ `v2`), uid 950:950, amd64 · 25971 байт `apply_tags_v2.py`
|
||||
- **План читается ТОЛЬКО как `/app/data/apply-plan.csv`** → подкладывать
|
||||
`/tmp/apply-plan-v3.csv` под этим именем
|
||||
- **Скрипт лежит в `/app/`**, план — в `/app/data/`. Путать нельзя (см. ПИТФОЛЛ 14)
|
||||
- Скрипт пишет `TIT2 TPE1 TPE2 TALB TCON TRCK` (все 6 полей сразу, режима «только genre» нет)
|
||||
- Строки скрипта: 76 `("new_genre","TCON","genre")` · 206 `TCON(...)` · 351 MP3-ветка ·
|
||||
515 верификация читает `TCON` обратно
|
||||
|
||||
### Пересканить Navidrome после правки тегов
|
||||
```bash
|
||||
@@ -183,6 +207,8 @@ backup_raw
|
||||
/tmp/verify_v3.py верификация: лог vs план
|
||||
/tmp/verify_v3b.py верификация: ПАПКА/ТРЕК-строки диффа из плана
|
||||
/tmp/verify_v3c.py верификация: аномалии (genre-дубли, Sbornik, пропуск пути)
|
||||
/tmp/parse_dry.py разбор лога dry-run по полям (только показанные 40 файлов!)
|
||||
/tmp/dryrun.log вывод успешного dry-run (копия с NAS)
|
||||
~/Developer/personal-os/tools/music-tags/build_fix_plan2.py генератор плана (пофикшен)
|
||||
```
|
||||
|
||||
@@ -253,10 +279,77 @@ Dry-run считает ФАЙЛЫ: album 28 · albumartist 6 · genre 4359 (в
|
||||
|
||||
| Дефект | Факт | Статус |
|
||||
|--------|------|--------|
|
||||
| **Жанры не в тегах** | В БД `genre` пусто у всех 7861; прогон 27 сен не писал `TCON` | Скрипт исправлен, **прогон нужен** |
|
||||
| **Жанры не в тегах** | В БД `genre` пусто у всех 7861; прогон 27 сен не писал `TCON` | Скрипт исправлен, dry-run доказал `TCON`. **Боевой прогон нужен** |
|
||||
| 🔴 **Боевой прогон сорвался** | Запущен без переопределения `CMD` → подставился `--dry-run` образа | **Ничего не записано. Повтор с явным CMD** |
|
||||
| Жанры в диффе | 427 строк / 911 групп, покрытие 7861 — не «правка», а повторная запись | Учтено |
|
||||
| Лог v3 устарел | 3 строки + 1 путь расходятся с планом после `fix_ruki`/`fix_rockopop` | Решено: план — эталон, лог не пересобираем |
|
||||
| Дифф: genre-группы | 211 ТРЕК-строк дублируют `new_genre`; 7 одиночек не добраны | **Ждём решения Alex** |
|
||||
| Дифф: genre-группы | 211 ТРЕК-строк дублируют `new_genre`; 7 одиночек не добраны | **Alex снял вопрос:** пишем полный набор, дифф не пересобираем |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 DRY-RUN и БОЕВОЙ ПРОГОН (27 сен, сессия ~30)
|
||||
|
||||
### ✅ DRY-RUN — ВЫПОЛНЕН УСПЕШНО
|
||||
|
||||
```bash
|
||||
scp -i ~/.ssh/id_rsa /tmp/apply-plan-v3.csv \
|
||||
truenas_admin@mallexxx.duckdns.org:/tmp/tw306/apply-plan.csv
|
||||
# md5 на NAS = 6b9e49b2baa3f1d1708e4566972266a9 (= локальному)
|
||||
```
|
||||
Вывод (`/tmp/dryrun.log`, 21955 B; на NAS `/tmp/tw306/dryrun.log`):
|
||||
```
|
||||
CSV: /app/data/apply-plan.csv
|
||||
строк в плане: 7861
|
||||
changed=yes требующих правки, но помеченных no: 4
|
||||
mp3 на диске: 7861 пропущено не-mp3: 562
|
||||
пропущено changed=no: 208
|
||||
не найдено на диске: 0 ← ни одного потерянного пути
|
||||
к обработке: 7653
|
||||
=== DRY-RUN — ничего не записано (7653 файлов) ===
|
||||
ИТОГО к правке: 7653
|
||||
```
|
||||
|
||||
**`TCON` доказан рабочим** — живой пример из лога:
|
||||
```
|
||||
!Барды/Владимир Высоцкий/Кони привередливые.mp3
|
||||
albumartist 'Vladimir Vysockij' -> 'Владимир Высоцкий'
|
||||
album '(Высоцкий)' -> 'Владимир Высоцкий'
|
||||
genre 'Разное' -> 'Бардовская песня'
|
||||
```
|
||||
|
||||
⚠️ **Лог печатает только первые 40 файлов** из 7653 (`... и ещё 7613`), **итога по полям
|
||||
в логе НЕТ** — только `ИТОГО к правке: 7653`. Не считать счётчики по 40 показанным
|
||||
файлам: получается ложное «genre меняется у 37», хотя в плане genre меняется у **4359**.
|
||||
|
||||
**Итог по полям берётся ИЗ ПЛАНА, а не из лога:**
|
||||
```
|
||||
genre 4359 · albumartist 7213 · album 2031 · track 441 · artist 381 · title 8
|
||||
plan.changed=yes 7653
|
||||
```
|
||||
|
||||
### 🔴 БОЕВОЙ ПРОГОН — НЕ СОСТОЯЛСЯ (запущен с неверным аргументом)
|
||||
|
||||
Запущено:
|
||||
```bash
|
||||
docker create --name twrun --entrypoint python3 \
|
||||
-v /tmp/tw306:/app/data:ro -v /mnt/RED_2TB/storage/Music:/music:rw \
|
||||
tagwriter:latest /app/apply_tags_v2.py # ← CMD НЕ переопределён
|
||||
docker start -a twrun
|
||||
```
|
||||
Результат: `exit=0`, но в `/tmp/tw306/run.log` строка
|
||||
`=== DRY-RUN — ничего не записано (7653 файлов) ===`.
|
||||
|
||||
**Причина:** у `tagwriter:latest` в `CMD` уже прописан `--dry-run`:
|
||||
```
|
||||
ENTRYPOINT = ["python3", "/app/apply_tags_v2.py"]
|
||||
CMD = ["--dry-run"]
|
||||
```
|
||||
При `docker create` без своего CMD образ подставил свой → скрипт получил `--dry-run`.
|
||||
|
||||
**✅ Ничего не записано, музыка не тронута, бэкап не потребовался.**
|
||||
|
||||
**Осталось перед повтором:** подтвердить в скрипте флаг боевого режима (в доках он
|
||||
не зафиксирован — проверялись только `--dry-run`), затем `docker create` **с явным CMD**.
|
||||
|
||||
---
|
||||
|
||||
@@ -273,10 +366,23 @@ Dry-run считает ФАЙЛЫ: album 28 · albumartist 6 · genre 4359 (в
|
||||
genre 911 · album 28 · albumartist 6
|
||||
Дифф на 100%: 7861 файл сопоставлен, не найдено 0
|
||||
Лог v3: 31 строка
|
||||
Dry-run 27 сен: план 7861 · mp3 на диске 7861 · не найдено 0 · к обработке 7653
|
||||
(пропущено changed=no 208, не-mp3 562) · лог печатает 40 файлов
|
||||
changed=yes но расхождений нет: 4 файла (Infected Mushroom ×3, Пушной)
|
||||
Боевой прогон: НЕ СОСТОЯЛСЯ — подставился `CMD=--dry-run` образа
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 ФАЙЛЫ НА NAS (рабочие, `/tmp/tw306/`)
|
||||
```
|
||||
apply-plan.csv md5 6b9e49b2baa3f1d1708e4566972266a9 (= /tmp/apply-plan-v3.csv)
|
||||
dryrun.log 21955 B — вывод успешного dry-run (есть копия на Mac /tmp/dryrun.log)
|
||||
run.log вывод сорвавшегося боевого прогона (снова DRY-RUN)
|
||||
check_album_applied*.py / verify_306*.py вспомогательные проверки
|
||||
|
||||
---
|
||||
|
||||
## 🧨 ПИТФОЛЛЫ
|
||||
|
||||
1. **`192.168.1.100` — чужая подсеть.** NAS: `mallexxx.duckdns.org`. Агент объявлял
|
||||
@@ -302,6 +408,19 @@ Dry-run считает ФАЙЛЫ: album 28 · albumartist 6 · genre 4359 (в
|
||||
совпадающее с `cur_genre` (дубль групповой строки). Не считать их списком правок.
|
||||
12. **Лог правок пересобирать ПОСЛЕ последнего фикса плана.** Иначе лог расходится с
|
||||
планом (так и вышло: `fix_ruki`/`fix_rockopop` прошли после генерации лога).
|
||||
13. 🔴 **`CMD` ОБРАЗА ПОДСТАВЛЯЕТСЯ АВТОМАТИЧЕСКИ.** У `tagwriter:latest` прописан
|
||||
`CMD=["--dry-run"]` → `docker create` БЕЗ своего CMD запускает dry-run, а не боевой
|
||||
прогон. Внешне выглядит как успех (`exit=0`), в логе — «ничего не записано».
|
||||
**Всегда:** `docker inspect --format 'CMD={{json .Config.Cmd}}'` ПЕРЕД `create`
|
||||
и явный флаг в `create`. Проверять в логе строку про DRY-RUN, не только `exit=0`.
|
||||
14. 🔴 **Скрипт в `/app/`, план в `/app/data/`.** `/app/data/apply_tags_v2.py` →
|
||||
`[Errno 2] No such file or directory`. Только `/app/data/` — это точка монтирования,
|
||||
скрипт туда не кладётся.
|
||||
15. **Лог dry-run неполный (40 файлов из 7653) и без итогов по полям.** Цифры по полям
|
||||
брать из плана (`cur_* != new_*`), не считать по обрезанному логу.
|
||||
16. **Не предлагать Alex выбор, которого он не делал.** «Только жанры или полный набор?»
|
||||
при живом плане = лишний круг и раздражение: набор очевиден из плана. Молчаливые
|
||||
умолчания не выдумывать, но и очевидное не переспрашивать.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -23,18 +23,45 @@ related:
|
||||
|
||||
# Music Tags Repair — TrueNAS (7906 → 7905 файлов)
|
||||
|
||||
> ## 🔴 АКТУАЛЬНОЕ СОСТОЯНИЕ (2026-09-27, сессия 29-ОКТИ) — ЧИТАЙ ЭТО ПЕРВЫМ
|
||||
> ## 🔴 АКТУАЛЬНОЕ СОСТОЯНИЕ (2026-09-27, сессия ~30) — ЧИТАЙ ЭТО ПЕРВЫМ
|
||||
>
|
||||
> ✅ **DRY-RUN ВЫПОЛНЕН УСПЕШНО.** План `/tmp/apply-plan-v3.csv` (md5
|
||||
> `6b9e49b2baa3f1d1708e4566972266a9`) скопирован на NAS как `/tmp/tw306/apply-plan.csv`
|
||||
> (md5 совпал). Вывод — `/tmp/dryrun.log` / NAS `/tmp/tw306/dryrun.log`:
|
||||
> ```
|
||||
> строк в плане 7861 · mp3 на диске 7861 · не найдено 0 · к обработке 7653
|
||||
> пропущено changed=no 208 · не-mp3 562 · DRY-RUN, ничего не записано
|
||||
> ```
|
||||
> **`TCON` доказан рабочим** — пример: `Кони привередливые.mp3` `genre 'Разное' → 'Бардовская песня'`.
|
||||
>
|
||||
> 🔴 **БОЕВОЙ ПРОГОН НЕ СОСТОЯЛСЯ — НИЧЕГО НЕ ЗАПИСАНО, музыка не тронута.**
|
||||
> Причина: у `tagwriter:latest` в образе прописан `CMD=["--dry-run"]` →
|
||||
> `docker create` без своего CMD запустил dry-run (`exit=0`, в логе снова DRY-RUN).
|
||||
> **Перед повтором:** `docker inspect tagwriter:latest --format 'CMD={{json .Config.Cmd}}'`
|
||||
> + явный флаг в `create`. См. § ПИТФОЛЛЫ доки плана.
|
||||
>
|
||||
> **Решение Alex (снят вопрос о диффе):** пишем **ПОЛНЫЙ НАБОР полей** (не только `TCON`),
|
||||
> дифф НЕ пересобираем. Требование «dry-run должен совпасть с `APPLY-PLAN-v3-changes`»
|
||||
> снято самим Alex: дифф считает ГРУППЫ, dry-run — ФАЙЛЫ, совпадение недостижимо by design.
|
||||
>
|
||||
> ✅ **КАНОННЫЙ ДИФФ v3 СОБРАН И ЗАКРЫТ:** `~/Downloads/music-tags/DIFF-base-vs-applyplan-v3.csv`
|
||||
> — **945 записей** (`ПАПКА` 711 · `ТРЕК` 234), `md5 bdb20c6ae00e7dfab4da2f76653fe084`.
|
||||
> Поля: `album` 28 · `albumartist` 6 · **`genre` 911 групп / 427 уникальных имён**.
|
||||
> `track` — **0** (весь блок убран как шум, см. ниже).
|
||||
> — **945 записей**, `md5 bdb20c6ae00e7dfab4da2f76653fe084`. Поля: `album` 28 ·
|
||||
> `albumartist` 6 · `genre` 911 (ГРУПП, не файлов). `track` — **0** (убран как шум).
|
||||
> ⚠️ **`genre` в диффе НЕ выдержан по `scope`:** в папке `!Radio/w 2008-07` дифф даёт
|
||||
> 5 значений, в плане 11 — одиночки отброшены правилом «ПАПКА, если ≥2 файла».
|
||||
> **Числа полей брать ИЗ ПЛАНА** (`cur_* != new_*`): `genre 4359 · albumartist 7213 ·
|
||||
> album 2031 · track 441 · artist 381 · title 8`.
|
||||
> База 7861 ↔ план 7861, сопоставлено 7861, **не найдено 0** (фильтр `path NOT LIKE 'backup%'`).
|
||||
> Источник: `/tmp/apply-plan-v3.csv` (7861, из `new_*` `APPLY-PLAN.csv` + правило корня;
|
||||
> **31 правка**, лог с колонкой `reason` — `~/Downloads/music-tags/APPLY-PLAN-v3-changes.csv`).
|
||||
> **31 правка**, лог с колонкой `reason` — `~/Downloads/music-tags/APPLY-PLAN-v3-changes.csv`,
|
||||
> ⚠️ **лог УСТАРЕЛ**: 3 строки расходятся с планом после `fix_ruki`/`fix_rockopop`).
|
||||
> Сборщик: `/tmp/build_canon_diff_v3.py`.
|
||||
>
|
||||
> 🔴 **ВЕРИФИКАЦИЯ v3 (2026-09-27) — dry-run НЕ ЗАПУЩЕН, 3 расхождения.** Полный разбор —
|
||||
> 🔴 **ЛОГ DRY-RUN НЕПОЛНЫЙ** — печатает 40 файлов из 7653, итогов по полям НЕТ.
|
||||
> Не считать «genre меняется у 37» — это 40 показанных файлов, а не итог.
|
||||
>
|
||||
> ✅ **ВЕРИФИКАЦИЯ v3 (2026-09-27) — ВЫПОЛНЕНА, 3 расхождения.** dry-run с тех пор ЗАПУЩЕН
|
||||
> и ПРОШЁЛ. Полный разбор —
|
||||
> [[personal/plans/music-artist-albumartist-repair]] § ВЕРИФИКАЦИЯ v3 ПЕРЕД DRY-RUN.
|
||||
> Коротко: (1) **лог `APPLY-PLAN-v3-changes.csv` УСТАРЕЛ** — писался до `fix_ruki.py`/
|
||||
> `fix_rockopop_track.py`, 3 строки врут (`Руки` вместо `Руки вверх`, `!rock_o_pop` вместо
|
||||
|
||||
Reference in new issue
Block a user