[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
6b8bba3336
commit
559b192028
3 files changed
+305
-14
No files matched your search
@@ -19,16 +19,16 @@ related:
|
||||
- '[[personal/tech/music-tags-repair-truenas]]'
|
||||
- '[[personal/plans/tagwriter-container]]'
|
||||
- '[[family/how-to/navidrome-truenas-android]]'
|
||||
status: session17-gluefix-applied-awaiting-alex-check
|
||||
|
||||
status: session17-gluefix-applied-image-deployed-dryrun-ok-awaiting-apply-go
|
||||
# Music `artist` + `albumartist` Repair — правила Alex и ход работ
|
||||
|
||||
## 🔵 СЕССИЯ 17 (2026-09-27) — ПОВТОРНЫЙ РУЧНОЙ ПРОХОД ДИФФА, ЧИТАТЬ ПЕРВЫМ
|
||||
|
||||
> ```
|
||||
> APPLY-PLAN.csv 7861 строка md5 2269466bbc08c018482b35c855569a8f (НЕ ИЗМЕНЁН)
|
||||
> DIFF-new-vs-38.csv 2845 строк md5 4e9e43318fb1c9dd353f96e3d125919c (НЕ ИЗМЕНЁН)
|
||||
> Снапшот RC совпадает с рабочими файлами байт-в-байт (проверено diff + md5)
|
||||
> APPLY-PLAN.csv 7861 строка md5 42d32ede85fef1b2fad6e2ce87012b7f (✅ ИЗМЕНЁН gluefix)
|
||||
> DIFF-new-vs-38.csv 2852 строки md5 4e073fe50c191cc50015d3f15f6a6d28 (✅ ПЕРЕГЕНЕРИРОВАН)
|
||||
> ДО правки было: APPLY-PLAN 2269466b… · DIFF 4e9e43318fb1c9dd353f96e3d125919c
|
||||
> Снапшот RC: ~/Downloads/music-tags/milestones/RC-20260927/ (состояние ДО gluefix)
|
||||
> ```
|
||||
>
|
||||
> **Alex потребовал ПОВТОРНЫЙ ручной проход по диффу.** ⚠️ Я ответил планом из 5 шагов
|
||||
@@ -152,6 +152,54 @@ status: session17-gluefix-applied-awaiting-alex-check
|
||||
> | `~/Downloads/music-tags/loss_kind.py` | разбор «881 потерь» → 0 реальных |
|
||||
> | `~/Downloads/music-tags/diff_new_vs_38.py` | генератор диффа (перегенерация) |
|
||||
|
||||
> ### 🔷 СЕССИЯ 17 (третья часть) — АУДИТ APPLY-СКРИПТА, СБОРКА ОБРАЗА, ЗАЛИВКА НА NAS
|
||||
>
|
||||
> Alex: «**Проверяй ещё раз руками apply script. Скажи алгоритм которым он будет применять
|
||||
> правки и найди если есть какие-то проблемы**» → затем «**Собирай**».
|
||||
>
|
||||
> Полный разбор алгоритма и питфоллов — в `[[personal/plans/tagwriter-container]]`
|
||||
> § «СЕССИЯ 17». Здесь — что касается ПЛАНА и приёмки.
|
||||
>
|
||||
> #### 🔴 ФИКС `normalize_track` по решению Alex
|
||||
> На вопрос «канонизировать `03/12` → `3/12` или оставить?» Alex: «**6 - оставлять**».
|
||||
> Функция переписана: мусор отбрасывается (`0`, `03/`, `/10`, `0/5`, `P@X@Tu*HCK*u`),
|
||||
> **форма записи сохраняется** (`095`→`095`, `03/12`→`03/12`, `01`→`01`).
|
||||
> Тест `test_normalize_track.py` — 16/16 OK. Записей `track` 344 → **335**.
|
||||
> MD5 скрипта `c7a2bc143e38820f2050310cbe01b799` в обеих копиях.
|
||||
>
|
||||
> #### 🔴 ТРИ ДЕФЕКТА DOCKERFILE (см. tagwriter-container.md для деталей)
|
||||
> | # | Дефект | Фикс |
|
||||
> |---|---|---|
|
||||
> | 1 | голый `Dockerfile` копирует **v1** `apply_tags.py` (5990 Б, без `TRCK`/`TPE2`) — та версия, что испортила 16 файлов | собирать только по `Dockerfile.v2` |
|
||||
> | 2 | `Dockerfile.v2`: `CMD` вместо `ENTRYPOINT` → `--apply` не передать (`exec: "--dry-run": not found`) | `ENTRYPOINT` + `CMD ["--dry-run"]` |
|
||||
> | 3 | `Dockerfile.v2` без `USER 950:950` → контейнер под root | `USER 950:950` |
|
||||
>
|
||||
> #### 🔴🔴 ПИТФОЛЛ: ARM-образ не запускается на NAS (amd64)
|
||||
> Mac собирает `linux/arm64`; NAS `x86_64`. Симптом: `exec format error`.
|
||||
> **Только `docker buildx build --platform linux/amd64 --load`.** `--load` обязателен.
|
||||
>
|
||||
> #### ✅ ЗАЛИТО НА NAS И ПРОВЕРЕНО
|
||||
> ```
|
||||
> образ: tagwriter:latest f9de5c14b923 amd64 137MB
|
||||
> внутри: uid=950 gid=950 · md5 c7a2bc143e38820f2050310cbe01b799 (= хостовый) · mutagen OK
|
||||
> план: apply-plan.csv 42d32ede85fef1b2fad6e2ce87012b7f (= боевой)
|
||||
> бэкап: apply-plan.csv.bak-before-gluefix-20260927-030612
|
||||
> backup/ библиотеки: /mnt/RED_2TB/storage/Music/backup — 50G (без неё exit 2)
|
||||
> ```
|
||||
> До залива на NAS были **устаревшие** артефакты: `tagwriter:latest` = v1, `tagwriter:v2` =
|
||||
> 16549 Б (не наш 25971), `apply-plan.csv` = `bf5093b3…`. **Не доверять артефактам на NAS
|
||||
> без сверки md5.**
|
||||
>
|
||||
> #### ✅ `--dry-run` НА РЕАЛЬНОЙ БИБЛИОТЕКЕ (exit=0, `/tmp/tw-dry.log` на NAS)
|
||||
> ```
|
||||
> строк в плане: 7861 · mp3 на диске: 7861 · пропущено не-mp3: 560
|
||||
> changed=no пропущено: 212 · не найдено на диске: 0 · к обработке: 7649
|
||||
> changed='no' с реальной правкой: 0
|
||||
> ```
|
||||
>
|
||||
> #### ⏳ ОСТАЛОСЬ: `--apply --verify` (7649 файлов) — ЖДЁТ «GO» ALEX
|
||||
> Порядок приёмки соблюдён: коммит ДО → правка → образ → dry-run → **ПРОВЕРКА АЛЕКСОМ** (ждём).
|
||||
|
||||
## 🟢 АКТУАЛЬНО НА КОНЕЦ СЕССИИ 16 (2026-09-27)
|
||||
|
||||
> ```
|
||||
|
||||
@@ -4,7 +4,7 @@ created: '2026-09-26'
|
||||
updated: '2026-09-27'
|
||||
type: plan
|
||||
namespace: personal
|
||||
status: session17-applyscript-audited-3-questions-open-no-run
|
||||
status: session17-image-built-deployed-dryrun-ok-awaiting-apply-go
|
||||
tags:
|
||||
- music
|
||||
- truenas
|
||||
@@ -91,16 +91,110 @@ related:
|
||||
> Перепроверка отдельным скриптом — **0 пробелов**. **Генератор по `r` внутри условия, которое
|
||||
> зависит от `r[c]`, даёт тождество. Писать условие явным циклом.**
|
||||
>
|
||||
> ### ⏳ СТАТУС ПОСЛЕ АУДИТА
|
||||
> ### ⏳ СТАТУС ПОСЛЕ АУДИТА → ✅ ЗАКРЫТО В СЕССИИ 17 (вторая половина)
|
||||
>
|
||||
> Три вопроса к Alex (пп. 3 и 5 — решение, п. 1/2 — действие перед прогоном):
|
||||
> 1. образ собрать — **билд впервые**, `Dockerfile.v2`;
|
||||
> 2. `changed=yes` без правок (12 строк) — снять флаг?
|
||||
> 3. `track` с ведущим нулём (11) — канонизировать в `1`/`3/12`?
|
||||
>
|
||||
> Боевой прогон не запущен.
|
||||
> Три вопроса заданы Alex, ответы получены и **выполнены**:
|
||||
> 1. образ собрать → ✅ собран и залит (см. ниже);
|
||||
> 2. `changed=yes` без правок → стало **1** вместо 12 (см. п. 5, эффект фикса формы);
|
||||
> 3. `track` с ведущим нулём → 🔴 **Alex: «6 - оставлять»** — форма записи НЕ меняется.
|
||||
|
||||
## 🔴 СТАТУС: БОЕВОЙ ПРОГОН НЕ ЗАПУЩЕН
|
||||
## ✅ СЕССИЯ 17 (вторая половина): ФИКС `normalize_track` + СБОРКА И ЗАЛИВКА ОБРАЗА
|
||||
|
||||
> Ответ Alex на п. 5: «**6 - оставлять**» → `normalize_track` переписан.
|
||||
>
|
||||
> ### 🔴 ФИКС `normalize_track`: отбрасывать мусор, НЕ менять ФОРМУ записи
|
||||
>
|
||||
> ```python
|
||||
> # БЫЛО (переписывало форму — 132 файла лишней записи):
|
||||
> num = int(v); return str(num) if num >= 1 else ""
|
||||
> if "/" in v: ... return f"{num}/{tot}"
|
||||
>
|
||||
> # СТАЛО:
|
||||
> if "/" in v:
|
||||
> a, b = v.split("/", 1)
|
||||
> if int(a) < 1 or int(b) < 1: return "" # "0/5" — мусор
|
||||
> return f"{a}/{b}" # форма сохраняется
|
||||
> return v if int(v) >= 1 else "" # "0" -> "", "01" -> "01"
|
||||
> ```
|
||||
>
|
||||
> | Вход | Было | Стало |
|
||||
> |---|---|---|
|
||||
> | `095` | `95` | **`095`** |
|
||||
> | `03/12` | `3/12` | **`03/12`** |
|
||||
> | `01` | `1` | **`01`** |
|
||||
> | `0`, `03/`, `/10`, `0/5`, `P@X@Tu*HCK*u` | `` | `` (мусор по-прежнему отбрасывается) |
|
||||
>
|
||||
> Тест: `~/Downloads/music-tags/test_normalize_track.py` — **16/16 OK**.
|
||||
> Эффект на боевом плане: записей `track` было 344 → стало **335** (9 лишних убрано);
|
||||
> кандидатов «меняется только форма» было 132 → **0**.
|
||||
> MD5 скрипта `c7a2bc143e38820f2050310cbe01b799` — **обе копии** (`~/Automation/music-tags/`
|
||||
> и `~/Downloads/music-tags/tagwriter/`).
|
||||
>
|
||||
> ### 🔴 ДВА ДЕФЕКТА `Dockerfile.v2`, найденных при первом запуске образа
|
||||
>
|
||||
> | # | Дефект | Симптом | Фикс |
|
||||
> |---|---|---|---|
|
||||
> | 1 | `CMD` вместо `ENTRYPOINT` | `docker run … tagwriter:latest --dry-run` → `exec: "--dry-run": executable file not found` — аргументы CLI не пробрасываются, `--apply` передать нельзя | `ENTRYPOINT ["python3", "/app/apply_tags_v2.py"]` + `CMD ["--dry-run"]` |
|
||||
> | 2 | нет `USER 950:950` | контейнер стартовал под root | `USER 950:950` (uid/gid `truenas_admin`, владелец `/storage/Music`) |
|
||||
>
|
||||
> Базовый образ — `python:3.11-slim` + `mutagen==1.47.0`. Итоговый `Dockerfile.v2`:
|
||||
> `FROM` · `pip install mutagen==1.47.0` · `WORKDIR /app` · `COPY apply_tags_v2.py` ·
|
||||
> `RUN chmod 755 /app/apply_tags_v2.py && chmod 755 /app` · `USER 950:950` · `ENTRYPOINT` · `CMD`.
|
||||
>
|
||||
> ### 🔴🔴 ГЛАВНЫЙ ПИТФОЛЛ: ПЛАТФОРМА ОБРАЗА — Mac ARM vs NAS amd64
|
||||
>
|
||||
> Первая сборка на Mac ушла под `linux/arm64`. На NAS запуск дал:
|
||||
> `WARNING: The requested image's platform (linux/arm64) does not match … (linux/amd64/v2)` →
|
||||
> `exec /usr/bin/sh: exec format error`.
|
||||
> NAS — **`x86_64`** (`docker version --format '{{.Server.Arch}}'` → `amd64`).
|
||||
>
|
||||
> **Собирать ТОЛЬКО так (кросс-платформа):**
|
||||
> ```bash
|
||||
> docker buildx build --platform linux/amd64 -f Dockerfile.v2 -t tagwriter:latest --load .
|
||||
> docker save tagwriter:latest -o /tmp/tagwriter-amd64.tar
|
||||
> scp /tmp/tagwriter-amd64.tar truenas_admin@mallexxx.duckdns.org:/tmp/
|
||||
> ssh … "docker load -i /tmp/tagwriter-amd64.tar"
|
||||
> ```
|
||||
> `--load` обязателен: без него `buildx` пишет только в кеш билдера, `docker images` пуст.
|
||||
>
|
||||
> ### ✅ ПРОВЕРКА ОБРАЗА НА NAS (фактами)
|
||||
> ```
|
||||
> docker run --rm --entrypoint sh tagwriter:latest -c 'id; md5sum /app/apply_tags_v2.py'
|
||||
> → uid=950 gid=950 groups=950
|
||||
> → c7a2bc143e38820f2050310cbe01b799 /app/apply_tags_v2.py (= хостовый)
|
||||
> mutagen OK
|
||||
> ```
|
||||
>
|
||||
> ### 🔴 СОСТОЯНИЕ NAS ДО ЗАЛИВА (три расхождения — не доверять старым артефактам)
|
||||
>
|
||||
> | Артефакт | Было на NAS | Стало |
|
||||
> |---|---|---|
|
||||
> | `tagwriter:latest` | **v1** `apply_tags.py`, 5990 Б, 15 часов | — |
|
||||
> | `tagwriter:v2` | `apply_tags_v2.py` 16549 Б, 4 часа (**не актуальная**, у нас 25971) | — |
|
||||
> | `tagwriter:latest` | — | `f9de5c14b923`, amd64, 137MB |
|
||||
> | `apply-plan.csv` | `bf5093b356a2c5c979037dbcf5d13a84` (**старый**) | `42d32ede85fef1b2fad6e2ce87012b7f` |
|
||||
>
|
||||
> Бэкап плана: `apply-plan.csv.bak-before-gluefix-20260927-030612`.
|
||||
> `backup/` библиотеки: `/mnt/RED_2TB/storage/Music/backup` — 50G, на месте
|
||||
> (без неё `cmd_apply()` делает `exit 2`).
|
||||
>
|
||||
> ### ✅ `--dry-run` НА РЕАЛЬНОЙ БИБЛИОТЕКЕ (exit=0)
|
||||
> ```
|
||||
> строк в плане: 7861
|
||||
> changed=no пропущено: 212
|
||||
> mp3 на диске: 7861
|
||||
> пропущено не-mp3: 560
|
||||
> не найдено на диске: 0
|
||||
> к обработке: 7649
|
||||
> ```
|
||||
> `changed=no` с реальной правкой — **0**. Все 7861 путь найден.
|
||||
> Расхождение `changed=yes` без правок: **12 → 1** (`The Prodigy - Girls (Rex The Dog Remix)`)
|
||||
> — эффект фикса формы `track`.
|
||||
>
|
||||
> ### ⏳ ОСТАЛОСЬ: `--apply --verify` (7649 файлов) — ЖДЁТ «GO» ALEX
|
||||
> Лог dry-run на NAS: `/tmp/tw-dry.log`. Мусор `/tmp/tagwriter*.tar` — удалить вручную.
|
||||
|
||||
## 🔴 СТАТУС: ОБРАЗ СОБРАН И ЗАЛИТ, DRY-RUN OK — ЖДЁТ «GO» НА `--apply --verify`
|
||||
|
||||
> План правится в сессиях 8-17
|
||||
> (дифф против 38-го прогона) — подробности в [[personal/plans/music-artist-albumartist-repair]] § «СЕССИЯ 17».
|
||||
|
||||
@@ -54,6 +54,15 @@ related:
|
||||
> ложных (3422 «кандидата» → 101 реальный дефект; `album == title` в основном ЛЕГИТИМНО).
|
||||
> Прежде чем называть класс дефектом — сверять с `cur_*` и по соседним файлам папки.
|
||||
>
|
||||
> ⚠️ **Обновлён до v2.1.0 (сессия 17, третья часть):** правила **W21–W30**.
|
||||
> Самое дорогое: **W21** — образ, собранный на Mac (`linux/arm64`), не запускается на
|
||||
> amd64-NAS (`exec format error`) → только `docker buildx --platform linux/amd64 --load`;
|
||||
> **W22** — `CMD` вместо `ENTRYPOINT` блокирует передачу `--apply`;
|
||||
> **W25** — `normalize_track` не должен менять ФОРМУ записи (`01`→`01`, `03/12`→`03/12`),
|
||||
> решение Alex «оставлять»; **W27** — детекторы по форме значения дают тысячи ложных
|
||||
> (222 кандидата → 101 реальный; `album == title` 149 → 0); **W30** — генератор по `r`
|
||||
> внутри условия от `r[c]` даёт тождество (ложные «7861 пробелов»).
|
||||
>
|
||||
> ⚠️ **Обновлён до v2.0.0 (сессия 15):** **D21** — 🔴 **КОРЕНЬ АРТИСТА = ОДИН АЛЬБОМ**:
|
||||
> файлы ПРЯМО в `<категория>/<артист>/` (без подпапки) считаются одним альбомом → `album` =
|
||||
> имя корня, `albumartist` = титульный исполнитель (= имя корня), **`cur_*` НЕ ЧИТАТЬ**.
|
||||
@@ -1085,6 +1094,146 @@ archive/APPLY-PLAN-v0-*.csv — устаревшие версии
|
||||
Суффикс `2` в имени файла-плана — источник ошибок: непонятно, какой применять. Один файл
|
||||
без суффикса, остальные явно помечены. Перед переименованием — `tar czf` снимок каталога.
|
||||
|
||||
### 🔴 W21 — образ собран на ARM (Mac) не запускается на amd64-NAS
|
||||
|
||||
Первый билд `tagwriter` на Mac ушёл под `linux/arm64`. На NAS (TrueNAS, `x86_64`):
|
||||
|
||||
```
|
||||
WARNING: The requested image's platform (linux/arm64) does not match
|
||||
the detected host platform (linux/amd64/v2)
|
||||
exec /usr/bin/sh: exec format error
|
||||
```
|
||||
|
||||
**Собирать кросс-платформенно и всегда `--load`:**
|
||||
|
||||
```bash
|
||||
docker buildx build --platform linux/amd64 -f Dockerfile.v2 -t tagwriter:latest --load .
|
||||
docker save tagwriter:latest -o /tmp/tagwriter-amd64.tar
|
||||
scp /tmp/tagwriter-amd64.tar truenas_admin@mallexxx.duckdns.org:/tmp/
|
||||
ssh … "docker load -i /tmp/tagwriter-amd64.tar"
|
||||
```
|
||||
|
||||
- `--load` **обязателен**: без него `buildx` кладёт образ только в кеш билдера, `docker images` пуст.
|
||||
- Архитектуру хоста проверять заранее: `docker version --format '{{.Server.Arch}}'`.
|
||||
- Приёмка после `docker load`: `docker run --rm --entrypoint sh <img> -c 'id; md5sum /app/<script>'`
|
||||
— сверить uid и md5 со хостовым. **`docker load` не доказывает, что внутри актуальный скрипт.**
|
||||
|
||||
### 🔴 W22 — `CMD` вместо `ENTRYPOINT`: аргументы CLI не пробрасываются
|
||||
|
||||
```dockerfile
|
||||
# ❌ docker run … tagwriter:latest --dry-run
|
||||
# → exec: "--dry-run": executable file not found in $PATH
|
||||
CMD ["python3", "/app/apply_tags.py"]
|
||||
|
||||
# ✅
|
||||
ENTRYPOINT ["python3", "/app/apply_tags_v2.py"]
|
||||
CMD ["--dry-run"]
|
||||
```
|
||||
|
||||
С `CMD` флаг `--apply` передать нельзя — режим боевой записи физически недоступен.
|
||||
|
||||
### 🔴 W23 — в одном проекте два Dockerfile с РАЗНЫМИ скриптами
|
||||
|
||||
`Dockerfile` → `COPY apply_tags.py` (**v1**: без `TRCK`, без `TPE2`, без фильтра не-mp3 — та
|
||||
версия, что испортила 16 файлов) · `Dockerfile.v2` → `apply_tags_v2.py`.
|
||||
|
||||
**Правило:** перед сборкой смотреть, что именно тянет `COPY`, и сверять размер/md5 скрипта
|
||||
внутри образа с рабочим. «Сборка прошла успешно» ничего не говорит о версии кода.
|
||||
Проверка: `docker run --rm --entrypoint sh <img> -c 'md5sum /app/*.py'`.
|
||||
|
||||
### 🔴 W24 — артефакты на NAS расходятся с локальными: сверять md5 перед прогоном
|
||||
|
||||
Перед боевым применением на NAS лежали **устаревшие** копии:
|
||||
|
||||
| Артефакт | На NAS было | Должно быть |
|
||||
|---|---|---|
|
||||
| `tagwriter:latest` | v1 `apply_tags.py`, 5990 Б, 15 ч | актуальный v2 |
|
||||
| `tagwriter:v2` | `apply_tags_v2.py` 16549 Б (наш — 25971 Б) | — |
|
||||
| `apply-plan.csv` | `bf5093b356a2c5c979037dbcf5d13a84` | `42d32ede85fef1b2fad6e2ce87012b7f` |
|
||||
|
||||
**Правило: перед `--apply` сверять md5 ПЛАНА на NAS с боевым локальным.** Если не совпал —
|
||||
заливать и бэкапить старый (`cp apply-plan.csv apply-plan.csv.bak-<tag>-<ts>`).
|
||||
|
||||
### 🔴 W25 — `normalize_track` не должен менять ФОРМУ записи
|
||||
|
||||
Канонизация `01` → `1`, `03/12` → `3/12` создаёт тег-запись там, где правки нет
|
||||
(в библиотеке было **132** таких файла). Решение Alex: «**оставлять**».
|
||||
|
||||
```python
|
||||
# ✅ отбрасывать мусор, форму сохранять
|
||||
v = (raw or "").strip()
|
||||
if not v or not TRACK_OK.match(v):
|
||||
return "" # "03/", "/10", "P@X@Tu*HCK*u"
|
||||
if "/" in v:
|
||||
a, b = v.split("/", 1)
|
||||
if int(a) < 1 or int(b) < 1:
|
||||
return "" # "0/5"
|
||||
return f"{a}/{b}" # форма как есть
|
||||
return v if int(v) >= 1 else "" # "0" -> "", "01" -> "01"
|
||||
```
|
||||
|
||||
**Общий принцип:** нормализатор отбраковывает невалидное, но не переписывает валидное.
|
||||
Иначе отчёт «изменено N файлов» врёт: изменений смысла нет, есть только запись.
|
||||
|
||||
### 🔴 W26 — любой детектор «разделителя» в теге матчит ВСЕ три тире
|
||||
|
||||
`(2012) Infected Mushroom – U r so fucked` — **en-dash `–` U+2013**, а не дефис. Регулярка
|
||||
по `-` строку не поймала, 1 файл из 7 остался неисправленным (верификатор показал `BAD … 1`).
|
||||
|
||||
```python
|
||||
DASH = r"[-–—]" # hyphen, en-dash, em-dash
|
||||
```
|
||||
|
||||
Технический шум в теге/имени папки прячется за разными вариантами одного символа
|
||||
(ср. A6: `(CD1)`/`(Disc 2)`).
|
||||
|
||||
### 🔴 W27 — детектор по ФОРМЕ значения даёт тысячи ложных срабатываний
|
||||
|
||||
Проход по диффу (`album`):
|
||||
|
||||
| Детектор | Кандидатов | Реальных |
|
||||
|---|---:|---:|
|
||||
| «дефис с пробелами в `album`» | 222 | **101** |
|
||||
| `album == title` | 149 | **0** |
|
||||
| «`new_album` входит в `folder`» | 3051 | **0** (ловит вложенность пути) |
|
||||
|
||||
`album == title` — в 130 папках это **одноимённые альбомы** (`Enigma/Sleep`, `Любэ/Атас`,
|
||||
`Сектор Газа/Колхозный панк`), у всех `cur_album == new_album`. Дефект только там, где
|
||||
`album` совпал с `title` у **одного** файла папки, а не у большинства.
|
||||
|
||||
**Правило:** прежде чем называть класс дефектом — проверить его против `cur_*` (план не
|
||||
выдумывал?) и по **соседним файлам папки** (A2/D22). Реальная находка — только СКЛЕЙКА
|
||||
`Родитель - Подпапка` и технический префикс `(год) Артист - `.
|
||||
|
||||
### 🔴 W28 — «ПОТЕРЯНО: N» в верификаторе ≠ потери правок
|
||||
|
||||
`verify_diff_completeness.py` дал `ПОТЕРЯНО: 2340` (881 после точной сверки). Разбор
|
||||
(`loss_kind.py`) показал: у **всех** новое значение ПРИСУТСТВУЕТ в строке `ПАПКА` — отличается
|
||||
только `old` (`<N разных>` при схлопывании, D16). **Правок, пропавших из диффа: 0.**
|
||||
|
||||
**Правило: перед словом «потеря» проверить, не покрыта ли пара строкой ПАПКА с другим
|
||||
`old`.** Схлопывание по `(папка, поле, новое)` делает разные `old` нормой.
|
||||
|
||||
### 🔴 W29 — проверять расхождение артефактов с ПРЕДЫДУЩИМ снапшотом фактом, а не догадкой
|
||||
|
||||
Alex: «**В rc этого не было.. это новые дефекты?**». Прямая сверка (`were_these_in_rc.py`)
|
||||
против снапшота RC: `7861/7861` строк совпадают, `отличий: 0`, все три класса присутствуют
|
||||
в RC в тех же количествах (18/77/6). → **дефекты НЕ новые, они были пропущены в RC-проходе.**
|
||||
|
||||
**Правило: на вопрос «это было раньше?» отвечать `diff` + `md5` по снапшотам, не рассуждением.**
|
||||
|
||||
### 🔴 W30 — `python3 -c` с генератором по `r` даёт тождество
|
||||
|
||||
```python
|
||||
# ❌ сравнивает значение САМО С СОБОЙ -> ложные «7861»
|
||||
any(c != (r[c] or "").strip() and r[c] for c in r if c.startswith("new_"))
|
||||
# ✅
|
||||
any(v != v.strip() for k, v in r.items() if k.startswith("new_") and v)
|
||||
```
|
||||
|
||||
Детектор пробелов отрапортовал 7861 нарушение, реально **0**. Условие, зависящее от `r[c]`,
|
||||
внутри генератора по `r` — писать явным циклом.
|
||||
|
||||
### 🔴 W17 — аудит по ОДНОМУ полю пропускает записи, где это поле уже верное
|
||||
|
||||
Детектор искал `new_artist == 'Сказочный сборник'` и дал 15 файлов. В папке их **17**:
|
||||
|
||||
Reference in new issue
Block a user