[2026-09-27] eagle: personal/plans/music-artist-albumartist-repair.md personal/plans/tagwriter-container.md personal/tech/id3-tag-repair.md
This commit is contained in:
1 parent
392cbc22db
commit
3946ccd352
3 files changed
+250
-12
No files matched your search
@@ -19,7 +19,7 @@ related:
|
||||
- '[[personal/tech/music-tags-repair-truenas]]'
|
||||
- '[[personal/plans/tagwriter-container]]'
|
||||
- '[[family/how-to/navidrome-truenas-android]]'
|
||||
status: manual-pass-17-defects-pending-approval
|
||||
status: session17-gluefix-applied-awaiting-alex-check
|
||||
|
||||
# Music `artist` + `albumartist` Repair — правила Alex и ход работ
|
||||
|
||||
@@ -42,7 +42,7 @@ status: manual-pass-17-defects-pending-approval
|
||||
> ⚠️ Бэкап **не** снимался: проход был read-only (ни одного байта не изменено). Бэкап —
|
||||
> обязателен только перед записью.
|
||||
>
|
||||
> ## РЕЗУЛЬТАТ ПОВТОРНОГО ПРОХОДА: 3 реальных дефекта (101 строка), НЕ 9
|
||||
> ## РЕЗУЛЬТАТ ПОВТОРНОГО ПРОХОДА: 3 реальных дефекта (102 строки), НЕ 9 — ✅ ИСПРАВЛЕНЫ
|
||||
>
|
||||
> 6 детекторов (`~/Downloads/music-tags/manual_scan.py`, `manual_scan2.py`), полный вывод —
|
||||
> `~/Downloads/music-tags/manual_scan_out.txt`.
|
||||
@@ -53,9 +53,10 @@ status: manual-pass-17-defects-pending-approval
|
||||
> | 2 | `album` = склейка «Категория - Подборка» | 77 | `Radio - 2009-10 Oktoberfest` → `2009-10 Oktoberfest` | `!Radio/*` |
|
||||
> | 3 | `album` = технический префикс папки | 6 | `(2001) Infected Mushroom - B.P. Empire` → `B.P. Empire` | `Infected Mushroom/*` |
|
||||
>
|
||||
> ⚠️ **Статус: ждут апрува Alex. В файл НЕ записано.** Правило: `album` = имя **подпапки**,
|
||||
> склейка `Родитель - Папка` запрещена (A3/D22). Технические префиксы — год издания
|
||||
> `(2001)`, имя артиста — не часть названия альбома (ср. A6: `(CD1)`/`(Disc 2)`).
|
||||
> ✅ **ПРИМЕНЕНО** (Alex: «Да, поправь все 3») — см. ниже «ПРИМЕНЕНО (сессия 17, вторая
|
||||
> половина)». Правило: `album` = имя **подпапки**, склейка `Родитель - Папка` запрещена (A3/D22).
|
||||
> Технические префиксы — год издания `(2001)`, имя артиста — не часть названия альбома
|
||||
> (ср. A6: `(CD1)`/`(Disc 2)`).
|
||||
>
|
||||
> ### ⚪ Ложные срабатывания детекторов (проверено фактами, НЕ дефекты)
|
||||
>
|
||||
@@ -73,7 +74,85 @@ status: manual-pass-17-defects-pending-approval
|
||||
> Прежде чем называть класс дефектом — проверять его **против `cur_album`** (план не выдумывал?)
|
||||
> и **по соседним файлам папки** (правило A2/D22).
|
||||
|
||||
## 🟢 АКТУАЛЬНО НА КОНЕЦ СЕССИИ 16 (2026-09-27) — читать это первым
|
||||
> ### ✅ ПРИМЕНЕНО (сессия 17, вторая половина) — 102 строки
|
||||
>
|
||||
> Alex: «**Да, поправь все 3**». Правка выполнена скриптом `~/Downloads/music-tags/fix_glue.py`
|
||||
> (dry-run по умолчанию, `--apply` пишет). Два прогона: 101 строка, затем +1 (см. питфолл тире).
|
||||
>
|
||||
> | # | дефект | строк | было → стало | где |
|
||||
> |---|---|---:|---|---|
|
||||
> | 1 | склейка «Категория - Подпапка» | **18** | `Бард - Авангард` → `Бард-авангард` | `!Рэп/Трофим/07 Бард-авангард` |
|
||||
> | 2 | склейка «Категория - Подборка» | **77** | `Radio - Старое` / `Radio - Df1` / `Radio - 2009-10 Oktoberfest` → имя подпапки | `!Radio/*` |
|
||||
> | 3 | технический префикс папки | **7** | `(2001) Infected Mushroom - B.P. Empire` → `B.P. Empire` | `Infected Mushroom/*` |
|
||||
>
|
||||
> #### ⚠️ ПОПРАВКА К ПРЕДЛОЖЕНИЮ: `Бард - Авангард` — НЕ категория
|
||||
> В первой версии отчёта я записал `Бард - Авангард` как склейку «категория - подпапка» с
|
||||
> целевым значением `Разное`. **Неверно — и это был бы выдуманный дефект (A2/D22).**
|
||||
> Проход по фактам: папка = `!Рэп/Трофим/07 Бард-авангард`, то есть `Бард-авангард` — **название
|
||||
> альбома Трофима** (2001). Значение через дефис с пробелами — опечатка-разделитель; норма —
|
||||
> как в имени папки: `Бард-авангард` (дефис без пробелов). **Данные Alex не давал — выведено
|
||||
> из пути, по правилу «факты важнее догадки».**
|
||||
>
|
||||
> #### 🔴 ПИТФОЛЛ: длинное тире `–` не поймано регуляркой по дефису
|
||||
> Первый прогон исправил 6 из 7 IM-строк. Осталась
|
||||
> `(2012) Infected Mushroom – U r so fucked (GANDI Remix)` — **en-dash `–` U+2013**, а не
|
||||
> дефис. Регулярка `-` её не матчила, верификатор показал `BAD … 1`. Починка — класс тире:
|
||||
>
|
||||
> ```python
|
||||
> DASH = r"[-–—]" # hyphen, en-dash, em-dash
|
||||
> RE_IM = re.compile(r"^\(\d{4}\)\s+Infected Mushroom\s+" + DASH + r"\s+(.+)$")
|
||||
> ```
|
||||
> **Правило: везде, где ищем «разделитель» в значении из ID3, матчить ВСЕ три тире.**
|
||||
> Это тот же класс, что A6 (`(CD1)` суффиксы): технический шум папки/тега прячется за
|
||||
> разными вариантами одного символа.
|
||||
>
|
||||
> #### Форма записи и контрольные суммы
|
||||
> ```
|
||||
> APPLY-PLAN.csv 2269466bbc08c018482b35c855569a8f → 42d32ede85fef1b2fad6e2ce87012b7f
|
||||
> DIFF-new-vs-38.csv 4e9e43318fb1c9dd353f96e3d125919c → 4e073fe50c191cc50015d3f15f6a6d28 (2852 строки)
|
||||
> бэкапы: APPLY-PLAN.csv.bak-gluefix-20260927-154547 (101) · …-154606 (1)
|
||||
> ```
|
||||
> Порядок соблюдён: **коммит ДО → правка → бэкап → ПРОВЕРКА** (ждёт Алекса). `changed=yes`
|
||||
> проставлен всем 102 строкам. Скрипт пишет через `tmp` + ревалидацию полей (16) + `os.replace`,
|
||||
> по схеме защиты от обрезки CSV (§5 `id3-tag-repair`).
|
||||
>
|
||||
> #### 🔴 УРОК: 101 строка прошла RC-ревью незамеченной — доказать фактом
|
||||
> Alex спросил: «**В rc этого не было.. это новые дефекты?**» Прямая проверка скриптом
|
||||
> `were_these_in_rc.py` против снапшота `milestones/RC-20260927/`:
|
||||
> ```
|
||||
> RC: 7861 строк | текущий: 7861 | одинаковых строк: 7861 | отличий: 0
|
||||
> Бард - X RC=18 сейчас=18
|
||||
> Radio - X RC=77 сейчас=77
|
||||
> (год) IM - X RC= 6 сейчас= 6
|
||||
> ```
|
||||
> → **дефекты НЕ новые, они присутствовали в RC в тех же количествах и были пропущены.**
|
||||
> RC-проход искал срабатывания по имени папки-артиста и не проверял значение на **склейку**.
|
||||
> **Вывод для будущих ревью: дифф проверять и на форму значения (склейка, префикс), не только
|
||||
> на согласованность с папкой.**
|
||||
>
|
||||
> #### ✅ Верификация после правки (вывод по САМОМУ файлу, `verify_glue.py`)
|
||||
> ```
|
||||
> Бард - Авангард (старое написание) 0 album='Бард-авангард' 18
|
||||
> Radio - X (склейка) 0 album='Старое' (Radio) 20
|
||||
> (год) IM - X (склейка) 0
|
||||
> ```
|
||||
> Контроль полноты (`verify_diff_completeness.py`): «ПОТЕРЯНО» = 881, **но это не потери** —
|
||||
> скрипт `loss_kind.py` показал: у всех 881 новое значение ПРИСУТСТВУЕТ в строке ПАПКА,
|
||||
> отличается только `old` (`<N разных>`, схлопывание D16). **Правок, пропавших из диффа: 0.**
|
||||
> `ЛИШНИХ строк в диффе: 0`.
|
||||
>
|
||||
> #### Артефакты сессии 17
|
||||
> | Файл | Назначение |
|
||||
> |---|---|
|
||||
> | `~/Downloads/music-tags/manual_scan.py`, `manual_scan2.py` | 6 детекторов по плану/диффу |
|
||||
> | `~/Downloads/music-tags/manual_scan_out.txt` | полный список кандидатов (3422) |
|
||||
> | `~/Downloads/music-tags/were_these_in_rc.py` | сверка со снапшотом RC (ответ на вопрос Alex) |
|
||||
> | `~/Downloads/music-tags/fix_glue.py` | правка 3 классов склейки (`--apply`) |
|
||||
> | `~/Downloads/music-tags/verify_glue.py` | верификация значений по файлу |
|
||||
> | `~/Downloads/music-tags/loss_kind.py` | разбор «881 потерь» → 0 реальных |
|
||||
> | `~/Downloads/music-tags/diff_new_vs_38.py` | генератор диффа (перегенерация) |
|
||||
|
||||
## 🟢 АКТУАЛЬНО НА КОНЕЦ СЕССИИ 16 (2026-09-27)
|
||||
|
||||
> ```
|
||||
> APPLY-PLAN.csv 7861 строка md5 2269466bbc08c018482b35c855569a8f
|
||||
|
||||
@@ -4,7 +4,7 @@ created: '2026-09-26'
|
||||
updated: '2026-09-27'
|
||||
type: plan
|
||||
namespace: personal
|
||||
status: v16-diff-session2-3594-rows-album-filled-radio-format-done-track-open
|
||||
status: session17-applyscript-audited-3-questions-open-no-run
|
||||
tags:
|
||||
- music
|
||||
- truenas
|
||||
@@ -20,10 +20,92 @@ related:
|
||||
---
|
||||
# tagwriter — применение тегов к MP3 (TrueNAS)
|
||||
|
||||
> 🔴 **СТАТУС: БОЕВОЙ ПРОГОН НЕ ЗАПУЩЕН.** План правится в сессиях 8-9
|
||||
> (дифф против 38-го прогона) — подробности в [[personal/plans/music-artist-albumartist-repair]] § «СЕССИЯ 8/9».
|
||||
> Актуальные MD5: `APPLY-PLAN.csv` = `d1fa36dc0fba72faeff08856369fca46` (7861 стр),
|
||||
> `DIFF-new-vs-38.csv` = `374ed1fed3abb7d9ec397025c0c88a2b` (4945 стр).
|
||||
## 🔴 СЕССИЯ 17: АУДИТ APPLY-СКРИПТА ПЕРЕД БОЕВЫМ ПРОГОНОМ — ЧИТАТЬ ПЕРВЫМ
|
||||
|
||||
> Alex: «**Проверяй ещё раз руками apply script. Скажи алгоритм которым он будет применять
|
||||
> правки и найди если есть какие-то проблемы.**»
|
||||
>
|
||||
> Аудит read-only, ничего не запускалось. Скрипты:
|
||||
> `~/Downloads/music-tags/audit_apply_script.py`, `audit_details.py`, `audit_critical.py`.
|
||||
>
|
||||
> ### АЛГОРИТМ (порядок исполнения, проверен по коду)
|
||||
>
|
||||
> | # | Шаг | Что делает |
|
||||
> |---|---|---|
|
||||
> | 1 | `_self_check()` | до записи: каждый фрейм `FIELD_MAP` создаётся в `_frames()` и покрыт `expected()`, иначе ABORT |
|
||||
> | 2 | `load_plan()` | читает `/app/data/apply-plan.csv` |
|
||||
> | 3 | `_check_changed_consistency()` | `changed=yes` ⟺ есть расхождение после нормализации |
|
||||
> | 4 | `build_disk_index()` | обход `/music`, **только `.mp3`**, папки `backup*` исключены |
|
||||
> | 5 | `build_jobs()` | `changed=no` → пропуск; `map_path()` (не выпускает за `/music`); нет в индексе → `missing` |
|
||||
> | 6 | `cmd_apply()` | нет `/music/backup` → `exit 2` |
|
||||
> | 7 | `apply_one()` ×N | `_preserved_frames()` (TDRC/COMM из v2→v1) → `delall` безусловно 6 фреймов → `add` непустых → `save(disk, v1=0, v2_version=3)` |
|
||||
> | 8 | `--verify` | read-back всех, MISMATCH → `/app/data/apply-report.csv` |
|
||||
>
|
||||
> ### ✅ ЧТО ПРОВЕРЕНО И БЕЗОПАСНО
|
||||
>
|
||||
> ```
|
||||
> колонки: 16/16, отсутствующих нет · дублей path: 0 · пробелов в new_*: 0
|
||||
> changed='no' c расхождением (потеря правки): 0
|
||||
> TRCK-мусор в new_track: 0 · new_title пуст → удаление TIT2: 0
|
||||
> save() в тот же путь · v1=0 · фильтр .mp3 · map_path не выпускает за /music · probe="1"
|
||||
> ```
|
||||
>
|
||||
> ### 🔴 ПРОБЛЕМЫ, НАЙДЕННЫЕ АУДИТОМ
|
||||
>
|
||||
> **1. ОБРАЗ `tagwriter` НЕ СОБРАН ВООБЩЕ.** `docker images` пуст — ни `tagwriter:latest`,
|
||||
> ни `tagwriter:v2`. На `2026-09-27` **билд выполняется впервые**. Обязателен `docker cp`
|
||||
> актуального `apply_tags_v2.py` (питфолл W12).
|
||||
>
|
||||
> **2. ДВА DOCKERFILE — РАЗНЫЕ СКРИПТЫ. Брать только `Dockerfile.v2`.**
|
||||
>
|
||||
> | Файл | `COPY` | Вердикт |
|
||||
> |---|---|---|
|
||||
> | `Dockerfile` | `apply_tags.py` (v1, 5990 Б) | 🔴 **устаревшая v1**: без `TRCK`, без `TPE2`, без фильтра не-mp3 — та версия, что испортила 16 файлов |
|
||||
> | `Dockerfile.v2` | `apply_tags_v2.py` | ✅ `python:3.11-slim` + `mutagen==1.47.0` |
|
||||
>
|
||||
> Копии `apply_tags_v2.py` (`~/Automation/...` и `~/Downloads/.../tagwriter/`) **совпадают по коду**,
|
||||
> различие только в docstring (`APPLY-PLAN-FINAL2.csv` vs `APPLY-PLAN.csv`).
|
||||
>
|
||||
> **3. 🟡 12 строк `changed=yes` без реальных правок** — все 6 полей `cur == new`:
|
||||
> `The Prodigy - Girls (Rex The Dog Remix)` · `Ночные Снайперы/Армия (2009)` (9 файлов) ·
|
||||
> `Infected Mushroom` (2). Тег перезапишется тем же значением: данные не портятся, но это
|
||||
> лишняя запись и ложная строка в `field_changes`. **Ждёт решения Alex — снять флаг или нет.**
|
||||
>
|
||||
> **4. 🟡 `--force` переворачивает проблему 3.** Обработает 212 `changed=no`, у которых
|
||||
> расхождений **0** (проверено) → лишние перезаписи. `--force` не нужен.
|
||||
>
|
||||
> **5. 🟡 TRCK канонизируется: `01` → `1`, `03/12` → `3/12`.** 11 файлов (Infected Mushroom,
|
||||
> Ночные Снайперы) имеют **корректный** тег в форме с ведущим нулём, но будут перезаписаны
|
||||
> из-за нормализации. Семантически эквивалентно, но это запись без изменения смысла.
|
||||
> **Ждёт решения Alex — канонизировать или нет.**
|
||||
>
|
||||
> ### 🔴 ПИТФОЛЛ АУДИТА: два скрипта дали 21 vs 12 — сравнивать track НАДО нормализованно
|
||||
>
|
||||
> `audit_apply_script.py` сравнивал `track` сырыми строками → `'01' != '1'` → **21 ложная**
|
||||
> строка «лишний changed». Строгий `audit_critical.py` нормализует `track` через тот же
|
||||
> `normalize_track()` → **12 реальных**. **Любое сравнение `track` — только после канонизации.**
|
||||
>
|
||||
> ### 🔴 ПИТФОЛЛ: `any(c != (r[c] or "").strip() and r[c] for c in r...)` — переменная `c` из `r` в генераторе
|
||||
>
|
||||
> Детектор пробелов в `new_*` сравнивал значение **само с собой** и вернул ложные «7861».
|
||||
> Перепроверка отдельным скриптом — **0 пробелов**. **Генератор по `r` внутри условия, которое
|
||||
> зависит от `r[c]`, даёт тождество. Писать условие явным циклом.**
|
||||
>
|
||||
> ### ⏳ СТАТУС ПОСЛЕ АУДИТА
|
||||
>
|
||||
> Три вопроса к Alex (пп. 3 и 5 — решение, п. 1/2 — действие перед прогоном):
|
||||
> 1. образ собрать — **билд впервые**, `Dockerfile.v2`;
|
||||
> 2. `changed=yes` без правок (12 строк) — снять флаг?
|
||||
> 3. `track` с ведущим нулём (11) — канонизировать в `1`/`3/12`?
|
||||
>
|
||||
> Боевой прогон не запущен.
|
||||
|
||||
## 🔴 СТАТУС: БОЕВОЙ ПРОГОН НЕ ЗАПУЩЕН
|
||||
|
||||
> План правится в сессиях 8-17
|
||||
> (дифф против 38-го прогона) — подробности в [[personal/plans/music-artist-albumartist-repair]] § «СЕССИЯ 17».
|
||||
> Актуальные MD5 (обновлены в сессии 17 после gluefix): `APPLY-PLAN.csv` = `42d32ede85fef1b2fad6e2ce87012b7f` (7861 стр),
|
||||
> `DIFF-new-vs-38.csv` = `4e073fe50c191cc50015d3f15f6a6d28` (2852 стр).
|
||||
> **Класс `Various Artists` поверх одного артиста — вычищен полностью** (детектор
|
||||
> `find_va_misuse.py` → `ПАПОК-КАНДИДАТОВ: 0`), корень `z Другое…` откачен на собственный `artist`.
|
||||
> Открыто: `track` (56 файлов с `238` + 9 с пустым при непустом `cur_track`), контейнер `snapcur` на NAS.
|
||||
@@ -517,16 +599,31 @@ docker start -a tw && docker rm -f tw
|
||||
22. **«Транслит в поле» ≠ дефект.** `Absolution`, `Sehnsucht`, `The Marshall Mathers LP` —
|
||||
настоящие названия. Дефект только транслит **русских** слов (`Sbornik_Novij_Rok`).
|
||||
Фильтр должен отделять язык-источник, а не «есть латиница».
|
||||
23. **Сравнение `track` только ПОСЛЕ нормализации.** `audit_apply_script.py` сравнивал сырые
|
||||
строки → `'01' != '1'` дало **21 ложную** строку «лишний `changed=yes`»; строгий
|
||||
`normalize_track()` дал **12 реальных**. Любой детектор по `track` обязан канонизировать
|
||||
обе стороны, иначе завышает объём работы в разы.
|
||||
24. **Генератор по `r` внутри условия, зависящего от `r[c]`, даёт тождество.**
|
||||
`any(c != (r[c] or "").strip() and r[c] for c in r if c.startswith("new_"))` сравнивает
|
||||
значение **само с собой** → ложные «7861 строк с пробелами». Реальность: **0**.
|
||||
**Писать такое условие явным `for`-циклом, а не comprehension.**
|
||||
25. **Два `Dockerfile` в одном каталоге = два разных скрипта внутри образа.**
|
||||
`Dockerfile` копирует `apply_tags.py` (v1), `Dockerfile.v2` — `apply_tags_v2.py`.
|
||||
Прогон по неверному файлу = возврат дефектов P1 (`TRCK`) и D3 (не-mp3).
|
||||
**Сверять `COPY` в Dockerfile с именем боевого скрипта перед `build`.**
|
||||
|
||||
## 9. Что осталось
|
||||
|
||||
| # | Шаг | Статус |
|
||||
|---|---|---|
|
||||
| 0 | **Собрать образ `tagwriter:v2`** — 🔴 **БИЛД ВЫПОЛНЯЕТСЯ ВПЕРВЫЕ** (образа на Mac нет вообще). Только `Dockerfile.v2` (не `Dockerfile` — в нём устаревшая v1). Затем `docker cp` актуального скрипта | ⏳ **новая задача сессии 17** |
|
||||
| 0a | **Правка 20 файлов в CSV** (`fix_20_files.py`) | ⏳ **скрипт написан, НЕ ЗАПУЩЕН** (решения Alex получены) |
|
||||
| 0b | Вопрос по `title='Вивальди А. - Зима (рок-обработка)'` — срезать префикс? | ⏳ открыт |
|
||||
| 0c | **Транслит русских слов в `new_album`** (204 файла: `Sbornik_Novij_Rok` 200 и др.) | ⏳ ждёт решения Alex |
|
||||
| 0d | `Филипок` / `Маленький_Мук` — `album='Сказочный сборник'` / транслит | ⏳ войдёт в 0c |
|
||||
| 1 | Боевой `--apply --verify` по 7861 | 🔴 **ЖДЁТ «go»** (после 0a–0c) |
|
||||
| 0e | **12 строк `changed=yes` без реальных правок** — снять флаг? | ⏳ **вопрос сессии 17** |
|
||||
| 0f | **`track` с ведущим нулём** (`01`, `03/12`) — канонизировать в `1`/`3/12`? 11 файлов | ⏳ **вопрос сессии 17** |
|
||||
| 1 | Боевой `--apply --verify` по 7861 | 🔴 **ЖДЁТ «go»** (после 0, 0a–0f) |
|
||||
| 2 | Приёмка Alex в UI (Navidrome/Jellyfin) | ⏳ |
|
||||
| 3 | Откат 40 из `backup_conv40/` | ⏳ |
|
||||
| 4 | Удаление 29 битых/DRM ([[personal/tech/music-broken-toload]]) | ⏳ |
|
||||
@@ -548,6 +645,9 @@ docker start -a tw && docker rm -f tw
|
||||
| `~/Automation/music-tags/Dockerfile.v2` | python:3.11-slim + mutagen 1.47.0 |
|
||||
| `~/Downloads/music-tags/tagwriter/rename_apply_plan.py` | раскладка имён CSV (одноразовый) |
|
||||
| **`~/Downloads/music-tags/tagwriter/fix_20_files.py`** | **правка 20 файлов в боевом CSV — НЕ ЗАПУЩЕН** |
|
||||
| `~/Downloads/music-tags/audit_apply_script.py` | аудит apply-скрипта против боевого CSV (сессия 17) |
|
||||
| `~/Downloads/music-tags/audit_details.py` | разбор `changed=yes` без правок + пробелы в `new_*` |
|
||||
| `~/Downloads/music-tags/audit_critical.py` | строгий аудит: `track` через `normalize_track()` (12 vs 21) |
|
||||
|
||||
### Бэкапы CSV
|
||||
|
||||
|
||||
@@ -61,6 +61,11 @@ related:
|
||||
> править выхваченные строки (сессия 15: 413 из 420 «нарушений» были ложными).
|
||||
> Полные формулировки — в `SKILL.md` скилла.
|
||||
|
||||
> ⚠️ **Обновлён до v2.1.0 (сессия 17):** **A7** (склейка `Родитель - Папка` и технический префикс
|
||||
> в `album`; 🔴 разделитель бывает ТРЁХ видов — `-`/`–`/`—`, матчить все) · **A8** (в контроле
|
||||
> полноты «ПОТЕРЯНО: 881» = смена ФОРМЫ записи при схлопывании D16, реальных потерь 0 —
|
||||
> сверять НОВОЕ значение, а не пару `old,new`). Полные формулировки — ниже.
|
||||
|
||||
## 📁 Артефакты проекта
|
||||
|
||||
**Путь:** `~/Developer/personal-os/tools/music-tags/`
|
||||
@@ -716,6 +721,60 @@ cur_album='Нечетный воин 2' → new_album='Нечётный Воин
|
||||
**Общий принцип:** технические суффиксы (`(CD1)`, `(Disc 2)`) — не часть названия альбома;
|
||||
перед записью значения сверять написание серии с нормой (ё, регистр).
|
||||
|
||||
### 🔴 A7 — СКЛЕЙКА «Родитель - Папка» / технический префикс в `album` (сессия 17)
|
||||
|
||||
Отдельный класс от A3 (имя подпапки) и A6 (суффиксы серии): `album` содержит **склейку**
|
||||
`Категория - Подпапка`, где левая часть — не артист альбома, а корень пути. Найдено 102 строки:
|
||||
|
||||
```
|
||||
Бард - Авангард -> Бард-авангард (18) !Рэп/Трофим/07 Бард-авангард
|
||||
Radio - Старое -> Старое (77) !Radio/* — album = имя подборки
|
||||
Radio - Df1 -> Df1
|
||||
(2001) Infected Mushroom - B.P. Empire -> B.P. Empire (7)
|
||||
```
|
||||
|
||||
Три формы склейки: **префикс-категория** (`Radio - `), **префикс-год+артист** (`(2001) IM - `),
|
||||
**название с ошибочным разделителем** (`Бард - Авангард` → норма `Бард-авангард`, как в имени
|
||||
папки). Правило: значение в `album` не должно содержать `Родитель - Ребёнок`; целевое значение
|
||||
брать из **имени подпапки** или **пути**, не выдумывать (A2/D22).
|
||||
|
||||
🔴 **Питфолл: разделитель бывает ТРЕМЯ разными символами.** Первый прогон исправил 6 из 7
|
||||
IM-строк — осталась `(2012) Infected Mushroom – U r so fucked` с **en-dash `–` (U+2013)**.
|
||||
Регулярка с дефисом её не матчит, и это **не даёт ошибки** — просто строка остаётся.
|
||||
|
||||
```python
|
||||
DASH = r"[-–—]" # hyphen U+002D, en-dash U+2013, em-dash U+2014
|
||||
RE_IM = re.compile(r"^\(\d{4}\)\s+Infected Mushroom\s+" + DASH + r"\s+(.+)$")
|
||||
```
|
||||
|
||||
**Любой поиск разделителя в значении из ID3 — матчить все три тире.** Соседний случай: NC-vs-NFD
|
||||
в именах папок (§8) — тот же класс «визуально одинаковое, побайтово разное».
|
||||
|
||||
🔴 **Питфолл ревью: дифф проверять не только на согласованность с папкой, но и на ФОРМУ значения.**
|
||||
RC-проход сверял `new_*` с именем папки-артиста и согласованностью по папке — **склейка внутри
|
||||
значения не проверялась**, 102 строки прошли ревью незамеченными. Детектор по форме (`re.search`
|
||||
разделителя в `album`) даёт много ложных (222 попадания на 101 реальных): отсеивать по `cur_album`
|
||||
и по соседним файлам папки.
|
||||
|
||||
**Скрипты:** `~/Downloads/music-tags/fix_glue.py` (`--apply`), `verify_glue.py`,
|
||||
`were_these_in_rc.py`, `loss_kind.py`.
|
||||
|
||||
### 🔴 A8 — «ПОТЕРЯНО» в контроле полноты может быть сменой ФОРМЫ записи, а не потерей
|
||||
|
||||
`verify_diff_completeness.py` после схлопывания диффа (D16) выдал `ПОТЕРЯНО: 881`. Реальных
|
||||
потерь — **0**. Скрипт строит эталон `(path, field, old, new)` и требует точного совпадения
|
||||
пары `(old, new)`; но при схлопывании у папки записывается `old = '<N разных>'`, поэтому
|
||||
**`old` не совпадает**, хотя `new` тот же.
|
||||
|
||||
```python
|
||||
# проверка: новое значение ПРИСУТСТВУЕТ в строке ПАПКА (не важно, какое там old)
|
||||
if any(c[1] == nv for c in coll[(folder_of(rel), field)]):
|
||||
form_change += 1 # смена формы записи, НЕ потеря
|
||||
```
|
||||
|
||||
**Правило:** при разборе «потерь» сверять **новое значение**, а не пару `(old, new)` — иначе
|
||||
отчёт пугает цифрой, за которой ничего нет. Скрипт `loss_kind.py`.
|
||||
|
||||
### 🔴 A5 — имя ПРОЕКТА вместо артиста + вложенные скобки в имени файла (сессия 9)
|
||||
|
||||
Класс: `artist` (и `albumartist`) = **название музыкального проекта**, а реальные исполнители
|
||||
|
||||
Reference in new issue
Block a user