diff --git a/personal/plans/balda-mm-phase4-agents.md b/personal/plans/balda-mm-phase4-agents.md index 9a6580e1..ed66f6d1 100644 --- a/personal/plans/balda-mm-phase4-agents.md +++ b/personal/plans/balda-mm-phase4-agents.md @@ -252,17 +252,18 @@ fails closed elsewhere»*. Для Mattermost `ask` **фейлится закры ## 6. План работ (по шагам) ### Шаг 1 — `~/agents` + `~/cli-auth` + контейнер-исполнитель (~2 ч) -1. `mkdir ~/agents`, права `admin:staff`; `~/cli-auth/{claude,codex}` (0700). +1. `mkdir ~/agents` (права `admin:staff`); `~/cli-auth/{claude,codex}` (0700) — **вне** `~/agents`. 2. `~/Docker/balda-executor/Dockerfile` — Node 24 + `codex` + `claude` + `git`. 3. `~/Docker/balda-executor/docker-compose.yml`: ```yaml volumes: - /Users/admin/agents:/agents:rw - - /Users/admin/cli-auth/claude:/root/.claude:rw # auth на хосте - - /Users/admin/cli-auth/codex:/root/.codex:rw # auth на хосте + - /Users/admin/cli-auth/claude:/root/.claude:rw # auth на хосте, вне /agents + - /Users/admin/cli-auth/codex:/root/.codex:rw # auth на хосте, вне /agents ``` + `agents-mounts.yaml` подключается генератором override-файла (`compose.override.yaml`), чтобы composefile не правился скриптом вручную. + 🔴 только `-v` + `docker compose up -d` — live-bind на macOS невозможен (§1a). 4. Авторизация один раз: `claude setup-token` на Mac → токен в `~/Docker/balda-executor/.env` (0600); `codex` — свой flow в `~/cli-auth/codex`. 5. Проверка: смонтированные auth видны (`docker exec ... ls /root/.claude`), @@ -316,7 +317,9 @@ fails closed elsewhere»*. Для Mattermost `ask` **фейлится закры 1. Порт моста — **8790** (взят свободный; проверить `lsof -i :8790` перед стартом). 2. Провайдер исполнителя — **claude** (подписка уже залогинена) или **codex**? 3. Нужен ли `ask`-апрув в будущем, или `allow_all` достаточно постоянно? -4. `~/cli-auth` (auth вне `~/agents`, агент не видит) vs `.cli-auth` внутри — по умолчанию **вне**. + +📌 Решено 2026-09-26: auth в **`~/cli-auth`** (вне `~/agents`), внешние проекты — +**только bind-mount**, live-bind вычеркнут. ## История - **2026-09-26**: создан. Решения Alex: папка `~/agents`, full access, управление @@ -330,6 +333,8 @@ fails closed elsewhere»*. Для Mattermost `ask` **фейлится закры требованию Alex: auth переживает пересборку образа и обновление CLI. ## Связанные заметки +- [[personal/plans/balda-mm-phase4-agents]] — Фаза 4 (план) +- [[personal/tech/macos-docker-virtiofs-mount-limits]] — 🔴 virtiofs: симлинки/live-bind/шары в контейнер - [[personal/projects/balda/balda-mm-delegation-plan]] — общий план (Фазы 4-5) - [[personal/projects/balda/balda-kraken-mm-deploy]] — Фаза 3 (✅ бот отвечает) - [[personal/plans/balda-mm-pr-plan]] — Фаза 2 (PR #8, 8/8 CI, ждёт ревью) diff --git a/personal/plans/music-tags-review/music-tags-review.md b/personal/plans/music-tags-review/music-tags-review.md index b5b3f578..048a1523 100755 --- a/personal/plans/music-tags-review/music-tags-review.md +++ b/personal/plans/music-tags-review/music-tags-review.md @@ -13,11 +13,16 @@ status: awaiting-approval > [!warning] Ничего не изменено > Это план. Ставь галочки, что одобряешь. После «go» — бэкап в `Music/backup/` и применение. +> [!tip] Блок 1 разобран вручную (2026-09-26) +> 28 файлов «требует решения» — прошёл глазами по одному. **10 артистов вписано вручную** +> (Hans Zimmer, Михаил Круг, Мумий Тролль, Kub vs Ray Charles, Lil Jon…), 18 — только title. +> См. [[1-needs-decision]]. + ## Что в каком блоке | Блок | Файлов | Что это значит | |---|---:|---| -| [[1-needs-decision\|Требует решения]] | 28 | Нет ни исполнителя, ни альбома. Взять неоткуда — только имя файла. | +| [[1-needs-decision\|Требует решения]] | 28 | Разобран вручную: 10 с артистом, 18 только title. | | **Средняя уверенность** (разбита по категориям) | 5787 | Восстановлено из имён файлов и структуры папок. | | [[3-high-confidence\|Высокая уверенность]] | 958 | Точная перекодировка CP1251 → UTF-8, обратимая без потерь. | diff --git a/personal/projects/balda/balda-mm-delegation-plan.md b/personal/projects/balda/balda-mm-delegation-plan.md index 68c03d41..1a94189b 100644 --- a/personal/projects/balda/balda-mm-delegation-plan.md +++ b/personal/projects/balda/balda-mm-delegation-plan.md @@ -17,6 +17,14 @@ > не останавливаться до исполнения. Детали по фазам вынесены в отдельные доки: > [[personal/projects/balda/mattermost-kraken-deploy]] (Фаза 1) · > [[personal/projects/balda/balda-mattermost-connector]] (Фаза 2). +> +> 🔴 **Фаза 4 — план готов, работа НЕ начата: [[personal/plans/balda-mm-phase4-agents]].** +> Решения Alex: папка исполнителя **`~/agents`**, режим **`allow_all`** (full access), +> auth CLI на хосте в **`~/cli-auth`** (вне `~/agents`), управление монтажами — новая +> секция «Agents» в Eagle Dashboard. +> **Проверено живыми тестами:** симлинк в контейнер не проезжает, live `mount --bind` +> на macOS недоступен, шары в контейнер не протянуть → внешние проекты только через +> `-v` + `docker compose up -d`. Разбор — [[personal/tech/macos-docker-virtiofs-mount-limits]]. --- diff --git a/personal/tech/eagle-dashboard-skill.md b/personal/tech/eagle-dashboard-skill.md new file mode 100644 index 00000000..f3151384 --- /dev/null +++ b/personal/tech/eagle-dashboard-skill.md @@ -0,0 +1,125 @@ +# eagle-dashboard (скилл) — зеркало знаний + +> Создан 2026-09-26. Зеркало скилла `eagle-dashboard` для случаев, когда скилл не загружен +> или нужен текстовый поиск по хранилищу. Источник истины — сам скилл +> (`~/.hermes/hermes-whale/skills/devops/eagle-dashboard/SKILL.md`). +> Дополнять **вместе** со скиллом, не расходясь. + +--- + +## Что это + +Eagle Dashboard — сервис-реестр + health-checks + управление lifecycle на Mac. +Живёт в `~/Developer/eagle-dash/`, поднят как launchd-агент, UI на http://localhost:8880. + +**Карта файлов (проверено 2026-09-26):** + +| Файл | Строк | Роль | +|---|---|---| +| `main.py` | 889 | FastAPI роуты | +| `templates/index.html` | 1248 | Alpine.js UI + все вкладки | +| `health.py` | 181 | health-чеки | +| `supervisor.py` | 290 | lifecycle процессов | + +**Вкладки:** `services` · `crons` · `pages` · `files` — роутинг через `?tab=`. +Планируется 5-я: `agents` (управление `~/agents`). + +**Health-типы:** `http` · `port` · `process` · `launchctl` · `none`. + +**Регистрация сервиса:** `services.yaml`, поле `health.type`. + +--- + +## 🔴 Критичные правила lifecycle + +- **НЕ убивать процессы.** Ни `kill`, ни `pkill`, ни `lsof -ti :8880 | xargs kill`. +- **Рестарт только по команде пользователя:** `launchctl kickstart gui/$(id -u)/com.eagle.dashboard`. +- **`launchctl bootout` — запрещено** (требует ребута для восстановления). +- **Hermes gateway (Eagle/Whale) — рестарт только через Dashboard API:** + `POST /api/services/hermes/restart`. Не `kill`, не `launchctl`. +- После рестарта — подождать 5 с, проверить `lsof`; если порт пуст — читать + `gateway.log`, НЕ рестартовать повторно. +- **Правки кода** → снять `__pycache__` + `launchctl kickstart -k` (иначе старый `.pyc`). +- «Стой»/«стоп» от пользователя → **ноль действий**, даже диагностики. + +--- + +## 🔴 Вкладка `agents` (планируется) — ограничения Docker на macOS + +Вкладка управляет `~/agents`, который монтируется в контейнер-исполнитель. +**Три ограничения доказаны живыми тестами 2026-09-26** (alpine:3.20, linux/arm64): + +### 1. Симлинк в контейнер НЕ проезжает + +Симлинк внутри bind-mounted каталога **битый** в контейнере: цель резолвится +относительно корня контейнера, где ничего не смонтировано. + +``` +host: -v /tmp/symtest/bind:/mnt с /mnt/target -> /tmp/symtest/outside +контейнер: cat /mnt/target/file.txt +→ No such file or directory +``` + +**«Подключить внешний проект симлинком» — невозможно.** + +### 2. Live `mount --bind` (nsenter) контейнеру не виден + +`nsenter -t 1 -m mount --bind` внутри VM → `BIND_OK`, но контейнер видит **пусто**. +Причина: Docker Desktop на macOS отдаёт файлы через **virtiofs**, который фиксирует +маппинг путей **на старте контейнера**. Проверено 3 прогонами (новый каталог, пауза 5 с, +каталог-до-старта) — все отрицательные. + +⚠️ Отдельная ловушка: `nsenter -t 1 -m` заходит в **VM**, путей мира macOS там нет — +хост-каталоги для VM надо создавать **внутри VM**. + +**Следствие: recreate обязателен.** `docker compose up -d` = 2-3 сек, `--privileged` не нужен. + +### 3. Сетевые шары (SMB/NFS) в контейнер не протянуть + +`mount_smbfs` в macOS → virtiofs его не видит → `-v /Volumes/share:/data` не работает. +Рекомендация: **`rsync` в `~/agents`** вместо прямого монтирования. + +### Матрица выбора + +| Способ | Папку? | Через тома? | Видно в контейнере | Итог | +|---|---|---|---|---| +| symlink | да | да | ✗ битый | ❌ | +| hardlink | **✗ нет** | ✗ нет | — | ✓ только файлы внутри тома | +| live `mount --bind` | да | да | ✗ | ❌ на macOS | +| **`-v` + recreate** | да | да | ✓ | ✅ рабочий путь | +| rsync-копия | да | да | ✓ | ✓ для шар/NAS | + +Hardlink **не линкует каталоги** и **не пересекает ФС** (`EXDEV`). Проверять `st_dev`. + +### Правила для вкладки + +- Вкладка рулит **манифестом монтажей** (`~/Developer/agents-mounts.yaml`) → генерирует + `compose.override.yaml` → `docker compose up -d`. **Не** создаёт симлинки. +- Вкладка **никогда не удаляет** содержимое `~/agents` — только отвязка от контейнера. +- Секреты/auth CLI — **вне** `~/agents` (`~/cli-auth`), отдельным `-v`, иначе агент + с rw на `/agents` читает свои же токены. + +Полный разбор: [[personal/tech/macos-docker-virtiofs-mount-limits]]. +Применение: [[personal/plans/balda-mm-phase4-agents]]. + +--- + +## Известные питфоллы (кратко) + +| Питфолл | Суть | Фикс | +|---|---|---| +| `_launchd_toggle()` | `launchctl list` = 0 даже когда процесс не запущен → кнопка инвертирована | проверять ключ `Disabled` в plist | +| `_msg` timeout | `setTimeout` держит stale-объект после `fetchCrons()` | захватывать source+id в замыкание, искать заново | +| `_list_launchd_crons()` | таймерные launchd-джобы показывали Resume (pid=None) | `"enabled": enabled` (plist загружен = включён) | +| EX_CONFIG (78) | launchd-джоб молча не работает | `~` не раскрывается → полный путь; либо скрипт сам отдаёт 78 | +| `lsof` not found | PATH под launchd = `/usr/bin:/bin` | полный путь `/usr/sbin/lsof` | +| `__pycache__` | старый `.pyc` отдаётся после правки | снять кэш + `kickstart -k` | +| PID для `http`/`port` | PID берётся через `lsof -ti :port` | если пусто — это норма для остановленного сервиса | + +--- + +## Связанные заметки + +- [[personal/tech/macos-docker-virtiofs-mount-limits]] — virtiofs: что не проезжает в контейнер +- [[personal/plans/balda-mm-phase4-agents]] — вкладка `agents` в контексте проекта +- скилл `eagle-dashboard` — источник истины diff --git a/personal/tech/macos-docker-virtiofs-mount-limits.md b/personal/tech/macos-docker-virtiofs-mount-limits.md new file mode 100644 index 00000000..8c5c8e93 --- /dev/null +++ b/personal/tech/macos-docker-virtiofs-mount-limits.md @@ -0,0 +1,167 @@ +# macOS Docker Desktop — что НЕ проезжает в контейнер (virtiofs) + +> Создан 2026-09-26. Статус: **проверено живыми тестами** (alpine:3.20, linux/arm64, +> Docker Desktop на macOS 26.6.1, Apple Silicon). +> Тема: границы проброса путей из мира macOS в контейнер. +> Все выводы получены прогонами, не по памяти. Команды воспроизведения — в §5. + +--- + +## 0. Главный вывод одной строкой + +На macOS Docker Desktop отдаёт контейнеру файлы **не через Linux `mount`**, а через +**virtiofs** — демон, который строит маппинг путей **в момент старта контейнера** +и знает только пути **мира macOS**, известные ему на старте. + +Всё, что появляется **позже** и **внутри VM** (ручной `mount`, шара, новый каталог), +изнутри VM видно корректно — **до контейнера не доходит**. Это не кэш: рестарт +не помогает, `sleep` не помогает. + +📌 На Linux-хосте (нативный Docker) этих ограничений **нет** — там +`nsenter`-трюки с `mount --bind` работают. Все выводы ниже — про **macOS**. + +--- + +## 1. Симлинки в контейнер НЕ проезжают + +Симлинк, чья цель лежит **вне** смонтированного каталога, в контейнере **битый**. + +``` +host: /tmp/symtest/outside/file.txt = "REAL CONTENT ON HOST" +bind: -v /tmp/symtest/bind:/mnt (внутри /mnt/target -> /tmp/symtest/outside) +контейнер: cat /mnt/target/file.txt +→ can't open '/mnt/target/file.txt': No such file or directory +``` + +Сам симлинк внутри **виден** (`lrwxrwxrwx target -> /tmp/symtest/outside`), но цель +резолвится **относительно корня контейнера**, где этого пути нет. Docker монтирует +только реальные пути — симлинки не разворачивает. + +**Следствие:** папка с симлинками на внешние цели в контейнере нерабочая, даже если +на хосте всё открывается. + +--- + +## 2. Live `mount --bind` (nsenter) контейнеру НЕ виден + +Схема обычная для Linux-хоста: + +```bash +docker run --rm --privileged --pid=host alpine nsenter -t 1 -m \ + mount --bind /host/source /host/agents/target +``` + +⚠️ **Первая ловушка (до самого mount):** `nsenter -t 1 -m` заходит в **VM**, а не в +macOS. Пути **мира macOS там не существуют**. Поэтому хост-путь для VM нужно +создавать **внутри VM** — например, в том же `nsenter -t 1 -m sh -c '...'`. + +Проверено **тремя** прогонами, результат одинаковый: + +| Прогон | Условие | Результат | +|---|---|---| +| 1 | каталог создан **после** старта контейнера + live bind | в контейнере пусто | +| 2 | ожидание 5 с (гипотеза «кэш атрибутов virtiofs») | пусто | +| 3 | каталог существовал **до** старта контейнера + bind **поверх** него | **пусто** | + +Изнутри VM всё корректно: + +``` +VM: cat /tmp/bindtest2/agents/existing/f.txt → "DATA2" ✓ файл есть +mount: BIND_OK ✓ смонтировалось +контейнер: cat /agents/existing/f.txt → No such file or directory ✗ +``` + +**Вывод:** live-bind для добавления каталогов в контейнер на macOS **недоступен**. +Единственный рабочий путь — **`-v` в compose + пересоздание контейнера** +(`docker compose up -d` = 2-3 сек, `--privileged` не нужен). + +--- + +## 3. Сетевые шары (SMB/NFS) в контейнер НЕ протянуть тем же путём + +- `mount_smbfs`/`mount_nfs` в macOS создаёт точку в **мире macOS** → virtiofs её + не видит → `-v /Volumes/share:/data` **не работает**. +- mount **внутри VM** через `nsenter` технически проходит, но: + - **не переживает рестарт Docker** (нужен startup-хук); + - требует `--privileged`; + - SMB/NFS не дают hardlink между экспортами, блокировки файлов ведут себя иначе — + сборщики/редакторы на шаре работают хуже, чем на локальном диске. + +**Рекомендация:** не тянуть шару в контейнер. Если данные на NAS — **`rsync` в +локальную папку** по требованию. Копия переживает всё и не требует privileged. + +--- + +## 4. Hardlink — чего он НЕ может (независимо от Docker) + +Это свойство ФС, не Docker: + +1. **Hardlink на каталог не делается.** Ни в APFS, ни в ext4, ни в NTFS. + `ln dir1 dir2` → `Operation not permitted`. У каталога появилась бы ссылка на + себя → цикл в дереве. Запрещено на уровне syscall. +2. **Между томами не работает.** Только внутри одной ФС (один `st_dev`), + иначе `EXDEV: Cross-device link`. + +**Следствие:** «подключить проект-каталог hardlink'ом извне» — **физически +невозможно**. Hardlink годится только для **файлов внутри одного тома**. + +--- + +## 5. Матрица: чем подключать путь в контейнер + +| Способ | Папку? | Через тома? | Видно в контейнере (macOS) | Итог | +|---|---|---|---|---| +| symlink | да | да | ✗ битый | ❌ для внешних целей | +| hardlink | **✗ нет** | ✗ нет | — | ✓ только файлы внутри тома | +| live `mount --bind` (nsenter) | да | да | ✗ | ❌ на macOS | +| **`-v` в compose + recreate** | да | да | ✓ | ✅ **рабочий путь** | +| rsync-копия | да | да | ✓ | ✓ когда данные на шаре/NAS | + +--- + +## 6. Команды воспроизведения + +```bash +# 1. Симлинк в контейнер +mkdir -p /tmp/symtest/outside /tmp/symtest/bind +echo "REAL CONTENT ON HOST" > /tmp/symtest/outside/file.txt +ln -sfn /tmp/symtest/outside /tmp/symtest/bind/target +docker run --rm --platform linux/arm64 -v /tmp/symtest/bind:/mnt alpine:3.20 \ + sh -c 'ls -la /mnt/; cat /mnt/target/file.txt' # → No such file or directory + +# 2. Live bind (внимание: пути создавать ВНУТРИ VM) +docker run -d --name t -v /tmp/bindtest2/agents:/agents alpine:3.20 sleep 300 +docker run --rm --privileged --pid=host alpine:3.20 nsenter -t 1 -m sh -c \ + 'mkdir -p /tmp/bindtest2/agents/existing /tmp/bindtest2/ext2 + echo DATA2 > /tmp/bindtest2/ext2/f.txt + mount --bind /tmp/bindtest2/ext2 /tmp/bindtest2/agents/existing' +docker exec t cat /agents/existing/f.txt # → No such file or directory + +# 3. Hardlink на каталог (должен упасть) +ln /tmp/a /tmp/b # → Operation not permitted +``` + +⚠️ Тестовые `docker run` тянут образы — гонять их на Mac, не на слабом хосте +(Kraken: buildkit-кэш и слои лягут на диск зря). + +--- + +## 7. Что делать в реальном проекте + +1. **Внешние каталоги** — только через **`-v` в compose** + `docker compose up -d`. + Манифест монтажей (список `name` + `host_path`) генерирует + `compose.override.yaml` — composefile не правится скриптом вручную. +2. **auth/секреты CLI — на хосте, ВНЕ рабочего каталога агента.** Иначе агент, + которому рабочий каталог смонтирован на запись, получает доступ к своим же + токенам. Монтировать отдельным `-v`. +3. **Шары** — `rsync` в локальную папку, не прямой mount. +4. **Hardlink** — только файлы внутри одного тома, с проверкой `st_dev`. +5. **Не строить архитектуру на live-mount'ах** — на macOS это тупик. + +--- + +## Связанные заметки +- [[personal/plans/balda-mm-phase4-agents]] — применение этих выводов (Фаза 4) +- [[personal/projects/balda/balda-mm-delegation-plan]] — общий план проекта +- скилл `eagle-dashboard` — сервис-реестр, health-типы, launchd +- скилл `docker-service-administration` — lifecycle контейнеров diff --git a/personal/tech/music-tags-repair-truenas.md b/personal/tech/music-tags-repair-truenas.md index 86912911..52ce674d 100755 --- a/personal/tech/music-tags-repair-truenas.md +++ b/personal/tech/music-tags-repair-truenas.md @@ -19,13 +19,86 @@ related: # Music Tags Repair — TrueNAS (7906 файлов) -> **Статус: ЭТАПЫ 1–2 ЗАВЕРШЕНЫ (2026-09-26). CSV v5 + ноты ревью отданы Alex. Правки файлов НЕ начаты.** +> **Статус: ЭТАПЫ 1–3 ЗАВЕРШЕНЫ (2026-09-26). CSV v5 + ноты ревью отданы Alex, блок 1 разобран вручную. Правки файлов НЕ начаты.** > Следующий шаг — апрув Alex по нотам ревью, затем бэкап + применение. -> Прогонялись **четыре волны** проверок: полный аудит всех строк (`audit_plan.py` + `final_gate.py`) → 6 багов, +> Прогонялись **пять волн** проверок: полный аудит всех строк (`audit_plan.py` + `final_gate.py`) → 6 багов, > третья волна по замечаниям Alex → 3 бага (en-dash + подстроковый поиск стоп-слов), -> **четвёртая волна (ручной проход) → 10 багов (track-номера, disc-track, восклицательные знаки, регистр)**. +> **четвёртая волна (ручной проход) → 10 багов (track-номера, disc-track, восклицательные знаки, регистр)**, +> **пятая волна (ручной разбор блока 1 глазами) → 28 файлов, 10 артистов вписано вручную**. > Итог v5: 6773 `fix`, mojibake = 0, 121 тест PASS, блок «требует решения» 296 → 28. +## 🖐 ПЯТАЯ ВОЛНА: РУЧНОЙ РАЗБОР БЛОКА 1 (2026-09-26) + +Alex: **«Ты проверил все вручную?»** → **«Без правила берешь и руками правишь. Без скриптов!!»** → +**«В md файлах блядь на аппрув! Какого хуя ты в id3 собрался лазить?!»** → **«ХУЯРЬ!»** + +Разбор всех **28 файлов блока «требует решения»** — вручную, по одному, без правил и регексов. +Результат записан в `personal/plans/music-tags-review/1-needs-decision.md` (vault, 6843 байта). + +### 🔴 ГЛАВНАЯ НАХОДКА ПЯТОЙ ВОЛНЫ: артист в скобках, разделителя нет + +Файл `01 Hit The Road Jack (Kub vs Ray Charles).mp3` — теги пустые, в имени: +`01` + название + артист **в скобках**. Разделителя ` - ` между artist и title нет, +поэтому `split_artist_title()` не сработал → **artist остался пустым, хотя он очевиден**. + +Правило «нет ` - ` → artist пусто» оставляет **тысячи** файлов без артиста там, где он есть: +в скобках, после `vs`, `feat.`, в имени папки. Это **системная дыра**, а не один файл. + +> 🔴 **ПИТФОЛЛ: отсутствие ` - ` НЕ означает отсутствие артиста.** +> Ищи артиста в скобках (`vs`, `feat.`, `&`, `with`), в префиксе до названия, в имени папки. +> Alex: «Тебе разве не очевидно что hit the road jack это название а kub vs ray charles это артист?» + +### Разбор 28 файлов вручную + +**А. Артист вписан руками — 10 файлов (очевидно из контекста):** + +| Файл | artist | title | Откуда ясно | +|---|---|---|---| +| `01 Hit The Road Jack (Kub vs Ray Charles)` | **Kub vs Ray Charles** | Hit the Road Jack | артист в скобках | +| `Pirates of the Caribbean` | **Hans Zimmer** feat. Dimitri Vegas & Like Mike | He's a Pirate | artist уже в title | +| `Interstellar` | **Hans Zimmer** | No Time for Caution | artist уже в title | +| `Кольщик` | **Михаил Круг** | Кольщик | известная песня | +| `Пропаганда-Супер детка` | **Пропаганда** | Супер детка | имя = artist-title | +| `detskiy_hor_benassi_satisfaction` | **Детский хор + Benny Benassi** | Satisfaction | имя файла | +| `06 Benassi I am a Dj` | **Benassi** | I Am a DJ | имя = artist + title | +| `Mymij_troll_kontrabanda` | **Мумий Тролль** | Контрабанда | имя файла | +| `lil jon` | **Lil Jon** | *(названия нет)* | имя файла | +| `Dj Riga ceh-126 Track` | **DJ Riga** | ceh-126 Track | имя = artist + title | + +**Б. Только title, artist пусто — 18 файлов** (Jellyfin → Unknown Artist, не угадываю). + +### ⚪ Что НЕ угадано (осознанно) + +- `Казанова`, `Младший лейтенант`, `Остаёмся зимовать` — теги мертвы, в имени только название. + Похоже на Сектор Газа / Вороваек, но **не пишу**. +- `НАШЕСТВИЕ 2009`, `Kazantip 2008` — это **события/фестивали**, не артисты. Перенесены в примечание. +- `Sensation White`, `Вертолёт башку сорвёт!(dj karas extra club)` — artist разведён (`Matisse`, `DJ Karas`), + остальное оставлено. + +### 🔴 ПИТФОЛЛ ПРАВОК MD: два подряд `patch` съедают строку + +При чистке дубля (`БОДРЯЧКОМ` попал в два блока) второй `patch` с тем же `old_string` **съел +закрывающую строку** блока → осиротевшая `- \`album\`: ⟨повреждено⟩ → —`. Пришлось читать файл +с `offset` и удалять точечно вторым патчем. + +> ⚠️ **После каждого `patch` в теле md — читать окрестность (`read_file` с offset) и сверять +> число чекбоксов.** Проверка: `grep -c '^- \[ \]'` = ожидаемое (28), `grep -c '^> - \['` = 0. + +**Верификация:** 28 чекбоксов, 28 уникальных файлов, 0 битых (`> - [ ]` — нет). + +### 📊 Цифры пятой волны + +| Метрика | Значение | +|---|---:| +| Блок 1 «требует решения» | 28 | +| Artist вписан вручную (А) | **10** | +| Только title, artist пусто (Б) | **18** | +| Файлов без artist всего | **8** (источника нет) | +| Размер `1-needs-decision.md` | 6843 байта | + +> ⚠️ **Важно: правки в ID3 НЕ делались.** Alex явно запретил лезть в теги до апрува — +> работа только в md-файлах Obsidian. Применение тегов = отдельный шаг после «go» + бэкап. + ## 🔴 ЧЕТВЁРТАЯ ВОЛНА: РУЧНОЙ ПРОХОД И TRACK-НОМЕРА (2026-09-26) Alex: **«Ты блядь руками пройди и пофикси все что мне предлагал кроме того что неочевидно!