Files
obsidian-vault/personal/tech/batch-data-edit-review-loop.md
T

76 lines
4.9 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Batch Data Edits with Human Review Loop (skill mirror)
created: '2026-09-26'
updated: '2026-09-26'
type: tech
namespace: personal
tags:
- skill
- data
- csv
- idempotency
- music
related:
- '[[personal/tech/music-tags-repair-truenas]]'
- '[[personal/plans/music-tags-wave38-fixes]]'
---
# Batch Data Edits with Human Review Loop — зеркало навыка
> Зеркало навыка `batch-data-edit-review-loop` (`~/.hermes/hermes-whale/skills/software-development/`).
> Канонический инстанс — `~/Downloads/music-tags/tag-fix-plan.csv` (ремонт ID3, 7906 строк).
## Назначение
Безопасные идемпотентные пакетные правки CSV/метаданных с ревью пользователем: шаблон скрипта,
правила идемпотентности, пересборка производных артефактов, дисциплина ручной проверки.
## Ключевые правила (сжато)
1. **Никогда не править на месте.** Скрипт в файл → бэкап → `.tmp` → ревалидация → `os.replace`.
2. **Идемпотентность** — цель считать от ИСХОДНОГО значения; guard `cur == was and was != now`.
Проверка: второй прогон = `0`.
3. **Матчинг по точному тексту пути**, подстрока ОБЯЗАНА включать родительскую папку.
4. **NFC-нормализация** при сравнении (NFC vs NFD визуально идентичны).
5. **Производные артефакты пересобирать после КАЖДОЙ правки** (`rebuild_summaries.py`),
приёмка `grep -c "<старое>" <derived>` → `0`.
6. **Инвариант полноты:** `sum(частей) == total`. Проверять **сумму**, не только группы.
7. **Не выдавать выборку за полную проверку.**
## 🔴 Уроки волны 38 (2026-09-26)
### 1. Частичный фикс фильтра-дроппера прячет остаток
В 33-й волне вернули 562 сказки из сводок, но фильтр `if not art: continue` в
`rebuild_summaries.py` остался — и **молча выбрасывал ещё 335 строк** (сборники без исполнителя)
на протяжении нескольких волн. Поймал только **инвариант полноты**
`single + multi + skip == 7906` (давало `7571`).
**Правило:** переопределяя метрику/фильтр — сохраняй полноту данных. Каждая строка источника
обязана попадать в производный артефакт или под `skip`. Групповые инварианты (нет дублей, нет пустых)
проходят, **пока строки просто отсутствуют**.
### 2. Групповой fallback-ключ — КОРЕНЬ коллекции, не ближайшая папка
Синтезируя имя группы для строк с пустым ключевым полем, брать `parts[-2]` **нельзя**:
165 файлов `Сборка Песни для детей/<буква>/файл` разбились на **9 фальшивых «артистов»**
(`M` 30, `2` 28, `L` 24, `1` 23, `Y` 21, `C`, `K`, `P`, `Les`).
**Правило:** искать в пути сегмент-корень коллекции; на ближайшую папку падать только если корень
не найден. Лечится тем же классом, что «имя подпапки-диска попало в тег» (волна 19).
### 3. Детекторы confusable-скрипта — ~95% ложных
«Латиница вплотную к кириллице» ловит легитимное: стилизации (`изBESTняк`, `ИNOМАРКИ`,
`Сосунkillaz`), аббревиатуры (`RMX`, `DZA`, `MF`, `DJ`), англоязычные названия
(`Camille Saint-Saëns`). Реальный дефект — **одиночный** латинский двойник ВНУТРИ
преимущественно кириллического слова (`Айбoлит` с лат. `o`).
**Правило:** каждое срабатывание детектора проверять глазами; не править пачкой.
В волне 38 из ~100 «срабатываний» реальными были **7**.
## Связанное
- [[personal/tech/music-tags-repair-truenas]] — волновой лог канонического инстанса
- [[personal/plans/music-tags-wave38-fixes]] — план/результат волны 38
- [[personal/tech/music-tags-rename-audit]] — аудит, нашедший эти дефекты