[2026-09-26] eagle: family/how-to/truenas-infrastructure.md personal/plans/music-tags-review/1-needs-decision.md personal/plans/music-tags-review/2-medium-confidence.md personal/plans/music-tags-review/3-high-confidence.md personal/plans/music-tags-review/music-tags-review.md personal/tech/music-tags-repair-truenas.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-26 15:01:21 +06:00
1 parent 1bf8320446
commit 7564ae26ac
6 files changed
+22581 -22429

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -1,20 +1,33 @@
---
title: Music Tags — Review
type: task
namespace: personal
tags: [music, jellyfin, tags, review, truenas]
status: awaiting-approval
---
# Music Tags — проверка тегов
**К правке:** 4774 файлов · **без изменений:** 3132
**К правке:** 4777 файлов · **без изменений:** 3129
> [!warning] Ничего не изменено
> Это план. Ставь галочки, что одобряешь. После «go» — бэкап в `Music/backup/` и применение.
| Блок | Файлов |
|---|---:|
| [[1-needs-decision\|Требует решения]] | 296 |
| [[2-medium-confidence\|Средняя уверенность]] | 2031 |
| [[3-high-confidence\|Высокая уверенность]] | 2447 |
## Что в каком блоке
| Блок | Файлов | Что это значит |
|---|---:|---|
| [[1-needs-decision\|Требует решения]] | 28 | Нет ни исполнителя, ни альбома. Взять неоткуда — только имя файла. |
| [[2-medium-confidence\|Средняя уверенность]] | 2144 | Восстановлено из имён файлов и структуры папок. |
| [[3-high-confidence\|Высокая уверенность]] | 2605 | Точная перекодировка CP1251 → UTF-8, обратимая без потерь. |
## Важное про блок 1
Попали только 28 файлов, где **нечего показать вообще**. Сборники и аудиосказки
(`!Детские/Детский хит`, `Сказки/*`) сюда **не входят** — у них есть альбом
(название сборника или сказки), а исполнителя у такого материала и не бывает.
Если подставить туда имя папки, получится мусор вида `artist = Сказки`
(238 треков одним «исполнителем») — от этого отказались.
## Формат
Каждый файл — чекбокс `- [ ]`. Под ним: поле, старое значение → **новое**, и источник
(`из имени файла`, `из структуры папок`, `кодировка` и т.д.).
`⟨повреждено⟩` = байты уничтожены (U+FFFD), восстановить нельзя — берётся из имени.
[[../tech/music-tags-repair-truenas|Техническая сторона →]]
@@ -22,6 +22,63 @@ related:
> Следующий шаг — апрув Alex по нотам ревью, затем бэкап + применение.
> Перед выдачей проведён **полный аудит всех 4774 строк** (`audit_plan.py` + `final_gate.py`) — найдено и исправлено 6 багов.
## 📌 ПЛАН ТРЕТЬЕЙ ВОЛНЫ (2026-09-26, апрув Alex) — «сам проставь, потом на апрув»
Alex: **«Давай ка дорогой пройди по файлу и сам проставь нормально все, а только потом мне на апрув,
я не собираюсь очевидные вещи руками лопать.»** + указал 2 конкретных дефекта.
| # | Замечание Alex | Причина | Что делаю |
|---|---|---|---|
| 1 | «не распознаются как чекбокс, убери треугольные скобки» | `render_grouped_doc.py` оборачивал блок в цитату `> [!info]`, чекбоксы получили префикс `> ` → Obsidian читает как цитату | ✅ убрано `> ` с чекбоксов и подпунктов, выноски оставлены |
| 2 | «`DJ Ivan Scratchin' – Welcome To China` — очевидно артист + название, почему склеено в title?» | `split_artist_title()` искал только `" - "` (ASCII-дефис). En-dash `–` / em-dash `—` не матчились | ✅ `SEP_RE` + `DASH_GLUE_RE`, `find_separator()` |
| 3 | «куча подобных» | скрытый баг: `any(w in norm(left) for w in EVENT_WORDS)` — **подстроковый** поиск. `"va" in "Ivan"` → True, и `DJ Ivan Scratchin'` отбрасывался | ✅ `has_word()` — токенный поиск |
### 🔴 КОРНЕВОЙ БАГ ТРЕТЬЕЙ ВОЛНЫ: подстроковый поиск стоп-слов
`EVENT_WORDS` и `RELEASE_WORDS` проверялись через `any(w in text for w in WORDS)`.
Это **подстрока**, не слово. Последствия:
| Слово из списка | Ложное срабатывание | Кого теряли |
|---|---|---|
| `va` | `"va" in "dj ivan scratchin'"` → True | `DJ Ivan Scratchin'` |
| `set` | `"set" in "sunset"` → True | `Sunset`-исполнители |
| `mix` | `"mix" in "mixes"` → True | папки `Remixes, Mixes` |
| `live` | `"live" in "delivery"` → True | — |
**Фикс:** `has_word(text, words)` — токенизация `re.split(r"[^0-9a-zа-яё]+", norm(text))`
и сравнение множеств. `Ivan` больше не матчит `va`, `Settle` не матчит `set`.
> 🔴 **ПИТФОЛЛ НА БУДУЩЕЕ: стоп-слова проверять ТОЛЬКО по токенам.**
> `"in" string` на списке коротких слов даёт ложные срабатывания на каждом втором имени.
### Три формы разделителя artist/title в библиотеке
| Форма | Пример | Регекс |
|---|---|---|
| пробелы с двух сторон | `Matisse – Back To Sensation` | `SEP_RE = \s+[-\u2013\u2014]\s+` |
| дефис приклеен слева | `Arno Cost & Norman Doray- Apocalypse` | `DASH_GLUE_RE`, только если слева >1 слова |
| дефис внутри слова (не сплит) | `Рок-н-ролл`, `БИ-2` | отвергается |
### 📊 Третья волна: цифры
| Метрика | v3 | **v4 (финал)** |
|---|---:|---:|
| `fix` | 4774 | **4777** |
| `no_change` | 3132 | 3129 |
| Ноты: «требует решения» | 296 | **28** ↓ в 10 раз |
| Ноты: средняя | 2031 | 2144 |
| Ноты: высокая | 2447 | 2605 |
| mojibake в выводе | 0 | **0** |
| Тесты | 65 | **65 + 15 новых = 80** |
**Почему «требует решения» упало 296 → 28:** в блок 1 попадали все файлы с пустым artist,
включая 155 сборников `Детский хит` и ~80 аудиосказок. У них **нет исполнителя по природе
материала**, но есть альбом. Критерий блока 1 изменён на
`not new_artist and not new_album` — «показать нечего вообще».
Осталось 28 файлов, где действительно пусто всё.
---
## 🔴 ВТОРАЯ ВОЛНА ИСПРАВЛЕНИЙ (2026-09-26, «Сам проверил весь файл на адекватность?»)
Alex: **«Сам проверил весь файл на адекватность? Чтобы я в очевидные вещи тебя не тыкал.»**