[2026-09-26] eagle: personal/plans/balda-mm-phase4-agents.md personal/plans/music-tags-review/music-tags-review.md personal/tech/agents-bridge.md personal/tech/music-tags-repair-truenas.md
This commit is contained in:
1 parent
d2f6a411f9
commit
dd9e081273
4 files changed
+492
-32
No files matched your search
@@ -1,8 +1,10 @@
|
|||||||
# Фаза 4 — исполнитель на Mac + `~/agents` + секция «Agents» в Eagle Dashboard
|
# Фаза 4 — исполнитель на Mac + `~/agents` + секция «Agents» в Eagle Dashboard
|
||||||
|
|
||||||
> План. **Шаг 1 выполнен** (2026-09-26): образ собран, контейнер `balda-executor` Up (healthy),
|
> План. **Шаги 1-2 выполнены** (2026-09-26): образ собран, контейнер `balda-executor` Up (healthy),
|
||||||
> `claude 2.1.283` + `codex 0.157.1` внутри, монтирования проверены в обе стороны.
|
> `claude 2.1.283` + `codex 0.157.1` внутри, монтирования проверены в обе стороны.
|
||||||
> ⏳ Осталось в шаге 1: логин CLI (нужен апрув на копирование auth-файлов).
|
> Мост `agents-bridge` :8790 поднят и протестирован (auth, идемпотентность, сквозной вызов CLI).
|
||||||
|
> 🔴 Осталось: **логин CLI делает Alex сам** (копирование auth-файлов отклонено); мост не в launchd;
|
||||||
|
> шаги 3-6 не начаты.
|
||||||
> Часть [[personal/projects/balda/balda-mm-delegation-plan]] (Фазы 4-5).
|
> Часть [[personal/projects/balda/balda-mm-delegation-plan]] (Фазы 4-5).
|
||||||
> Предыдущее: [[personal/projects/balda/balda-kraken-mm-deploy]] (Фаза 3 ✅ — бот отвечает Alex).
|
> Предыдущее: [[personal/projects/balda/balda-kraken-mm-deploy]] (Фаза 3 ✅ — бот отвечает Alex).
|
||||||
|
|
||||||
@@ -71,13 +73,12 @@ diff + тесты + коммит → Балда → Mattermost
|
|||||||
| Codex auth | `~/cli-auth/codex` | `/root/.codex` | 0700 |
|
| Codex auth | `~/cli-auth/codex` | `/root/.codex` | 0700 |
|
||||||
| OAuth-токен Claude | `~/Docker/balda-executor/.env` | env | 0600 |
|
| OAuth-токен Claude | `~/Docker/balda-executor/.env` | env | 0600 |
|
||||||
|
|
||||||
📌 **Основной путь авторизации — не `claude setup-token`, а копия auth-файлов** из
|
📌 **Авторизацию CLI делает Alex сам** (решение 2026-09-26). Копирование auth-файлов из
|
||||||
`~/.claude`/`~/.codex`. Токен в `.env` — запасной вариант для headless без монтирования.
|
`~/.claude`/`~/.codex` в `~/cli-auth` **отклонено** — я эти файлы не читаю и не копирую.
|
||||||
Выбранный вариант: копируются `~/.claude/.credentials.json` + `~/.claude/.claude.json` и
|
До его логина любая задача вернёт `Not logged in · Please run /login` (это ответ Claude Code,
|
||||||
`~/.codex/auth.json` + `~/.codex/config.toml`. Полные каталоги **не** копируются:
|
а не ошибка моста — конвейер при этом доказанно рабочий).
|
||||||
`~/.codex` содержит ~640 МБ sqlite-логов/состояний (`logs_2.sqlite`, `state_5.sqlite`,
|
|
||||||
`memories_1.sqlite`, `queue_1.sqlite`) — исполнителю не нужны, а вес и шум дают.
|
|
||||||
|
|
||||||
|
Токен `CLAUDE_CODE_OAUTH_TOKEN` в `.env` контейнера — запасной путь для headless без монтирования.
|
||||||
Пересборка образа и обновление CLI auth не сбрасывают. Токены вне `/agents` → агент их не видит.
|
Пересборка образа и обновление CLI auth не сбрасывают. Токены вне `/agents` → агент их не видит.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -180,25 +181,77 @@ docker-compose restart # проверка переживан
|
|||||||
⚠️ `deploy.resources.limits.memory: 8G` из черновика **убран**: в не-swarm compose
|
⚠️ `deploy.resources.limits.memory: 8G` из черновика **убран**: в не-swarm compose
|
||||||
эта секция молча игнорируется, лимит создавал ложное ощущение защиты.
|
эта секция молча игнорируется, лимит создавал ложное ощущение защиты.
|
||||||
|
|
||||||
#### ⏳ Осталось в шаге 1: логин CLI (ждёт апрува)
|
#### ✅ Логин CLI — зона Alex (не автоматизируется)
|
||||||
|
|
||||||
`~/cli-auth/claude` пуст, в `~/cli-auth/codex` только `tmp/`. Копировать **только auth-файлы**,
|
`~/cli-auth/claude` пуст, в `~/cli-auth/codex` только `tmp/`.
|
||||||
не целые каталоги (`~/.codex` ≈ 640 МБ служебных sqlite — агенту не нужны):
|
|
||||||
|
|
||||||
| CLI | Хост | Куда |
|
🔴 Копирование auth-файлов **отклонено Alex** («авторизую я, копировать из кредсы не надо»).
|
||||||
|---|---|---|
|
Не предлагать повторно, не читать `~/.claude/.credentials.json`, `~/.codex/auth.json`.
|
||||||
| claude | `~/.claude/.credentials.json`, `~/.claude/.claude.json` | `~/cli-auth/claude/` |
|
Признак незалогиненного исполнителя в ответе задачи: `Not logged in · Please run /login`.
|
||||||
| codex | `~/.codex/auth.json`, `~/.codex/config.toml` | `~/cli-auth/codex/` |
|
|
||||||
|
|
||||||
📌 В `~/cli-auth` кладётся **копия** (оригиналы на месте, `~/.claude` не переезжает):
|
### ✅ Шаг 2 ВЫПОЛНЕН (2026-09-26) — мост `agents-bridge`
|
||||||
у агента-исполнителя свои токены, изолированные от рабочих. Права `~/cli-auth` = 0700.
|
|
||||||
|
|
||||||
**2. Мост (~3-4 ч)**
|
Проект: `~/Developer/agents-bridge/` (FastAPI, python из `~/Developer/eagle-dash/.venv`, py3.14).
|
||||||
`~/Developer/agents-bridge/`, FastAPI :8790, `POST /task` (idempotency), `GET /task/{id}`, `GET /healthz`;
|
|
||||||
запуск CLI headless в контейнере; лимит 1-2 задач; shared secret.
|
|
||||||
|
|
||||||
**3. Сеть (~1 ч)**
|
| Файл | Роль |
|
||||||
Cloudflare Tunnel: добавить published route `agents-bridge.qentra.top` → HTTP `localhost:8790` +
|
|---|---|
|
||||||
|
| `app.py` | роуты, авторизация, лимит параллельности, ThreadPoolExecutor |
|
||||||
|
| `store.py` | SQLite WAL: `tasks` + UNIQUE-индекс по `idempotency_key` |
|
||||||
|
| `executor.py` | `docker exec` в контейнер, провайдеры claude/codex, таймаут, обрезка вывода |
|
||||||
|
| `config.py` | чтение `.env` (минимальный парсер, без python-dotenv на старте) |
|
||||||
|
| `.env` | 0600, `BRIDGE_SECRET` (64 симв.), **не коммитить** |
|
||||||
|
| `.env.example` | шаблон без секретов |
|
||||||
|
| `state.sqlite3` | статусы задач, WAL |
|
||||||
|
|
||||||
|
**API:**
|
||||||
|
```
|
||||||
|
GET /healthz → статус моста + контейнера (без секрета)
|
||||||
|
POST /task → 202 {task_id, status} | 200 (идемпотентный повтор) | 401 | 429 | 400
|
||||||
|
GET /task/{task_id} → статус + stdout/stderr/exit_code
|
||||||
|
GET /tasks?limit=N → последние задачи
|
||||||
|
```
|
||||||
|
|
||||||
|
**Авторизация:** заголовок `X-Bridge-Secret` на всех `/task*`. Идемпотентность — заголовок
|
||||||
|
`Idempotency-Key`; повтор возвращает **тот же** `task_id` со HTTP **200** (первый ответ — 202).
|
||||||
|
|
||||||
|
**Проверено живьём (2026-09-26):**
|
||||||
|
|
||||||
|
| Проверка | Результат |
|
||||||
|
|---|---|
|
||||||
|
| `POST /task` без секрета / с неверным | 401 / 401 ✅ |
|
||||||
|
| Два POST с одним `Idempotency-Key` | один `task_id` ✅ |
|
||||||
|
| Задача дошла до CLI в контейнере | ответ CLI вернулся ✅ |
|
||||||
|
| Статус в SQLite (WAL) | ✅ |
|
||||||
|
| `/healthz` видит контейнер | `container_running: true` ✅ |
|
||||||
|
|
||||||
|
Ответ `/healthz`:
|
||||||
|
```json
|
||||||
|
{"status":"ok","container":"balda-executor","container_running":true,
|
||||||
|
"provider":"claude","secret_configured":true,"active_tasks":0,"max_concurrent":1}
|
||||||
|
```
|
||||||
|
|
||||||
|
Результат сквозной пробы (до логина CLI): `status=failed, exit_code=1,
|
||||||
|
stdout='Not logged in · Please run /login'` — **это ожидаемо** и доказывает, что
|
||||||
|
путь Kraken → Mac → контейнер → CLI проходит целиком.
|
||||||
|
|
||||||
|
**Запуск (вручную, до launchd):**
|
||||||
|
```bash
|
||||||
|
cd ~/Developer/agents-bridge
|
||||||
|
~/Developer/eagle-dash/.venv/bin/python -m uvicorn app:app --host 127.0.0.1 --port 8790
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 🔴 Питфолл: `BRIDGE_SECRET` и redaction Hermes
|
||||||
|
|
||||||
|
Команда, создающая `.env` через `python -c` с f-строкой `BRIDGE_SECRET={...}`, в логе выглядит
|
||||||
|
обрезанной (`E...cret written`) — **это редакция секретов Hermes, файл на диске цел**.
|
||||||
|
Проверять содержимое не чтением файла, а через awk с маскировкой:
|
||||||
|
```bash
|
||||||
|
/usr/bin/awk -F= '{ if ($1 ~ /SECRET|TOKEN|KEY|PASSWORD/) print $1"=<redacted len "length($2)">"; else print }' .env
|
||||||
|
```
|
||||||
|
`read_file` на `.env` отказывает по определению (secret-bearing file).
|
||||||
|
|
||||||
|
**3. Сеть (~1 ч)** — Cloudflare Tunnel
|
||||||
|
Добавить published route `agents-bridge.qentra.top` → HTTP `localhost:8790` +
|
||||||
Access Application. Токен и процесс cloudflared не трогаются. Проверка: `curl` извне на `/healthz`.
|
Access Application. Токен и процесс cloudflared не трогаются. Проверка: `curl` извне на `/healthz`.
|
||||||
⚠️ hostname — **одноуровневый** (двухуровневые дают TLS handshake failure).
|
⚠️ hostname — **одноуровневый** (двухуровневые дают TLS handshake failure).
|
||||||
|
|
||||||
@@ -228,16 +281,23 @@ MCP-инструмент в Балде → `POST /task`; проба `echo ok > /
|
|||||||
|
|
||||||
## 8. Открыто
|
## 8. Открыто
|
||||||
|
|
||||||
1. ~~Провайдер исполнителя — claude или codex~~ → **claude** (оба в образе, переключение `EXECUTOR_PROVIDER`)
|
1. ~~Провайдер исполнителя~~ → **claude** (оба в образе, переключение `EXECUTOR_PROVIDER`)
|
||||||
2. ~~Нужен ли `ask`-апрув в будущем~~ → при `allow_all` не нужен; при потребности начинать с варианта B (апрув в мосте, ~0.5 дня)
|
2. ~~Нужен ли `ask`-апрув~~ → при `allow_all` не нужен; при потребности начинать с B (апрув в мосте, ~0.5 дня)
|
||||||
3. Hostname для моста (`agents-bridge.qentra.top`?) — ждёт шага 3
|
3. 🔴 **Логин CLI — делает Alex сам.** Копирование auth-файлов отклонено; до логина задачи
|
||||||
4. ⏳ **Апрув на копирование auth-файлов CLI** в `~/cli-auth` — блокирует завершение шага 1
|
возвращают `Not logged in`
|
||||||
5. Порт моста `8790` — проверено, свободен (`lsof -nP -i :8790`)
|
4. 🔴 **Мост не в launchd** — поднят вручную (`uvicorn` в фоне), при перезагрузке Mac умрёт.
|
||||||
|
Плейт `com.agents.bridge` **обязателен до шага 3**: туннель опубликует URL, который может
|
||||||
|
вести в закрытый порт. Предложено, ждёт команды Alex
|
||||||
|
5. Hostname моста — `agents-bridge.qentra.top` (шаг 3, ждёт public route в Cloud Zero Trust)
|
||||||
|
6. Порт `8790` — проверено, свободен (`lsof -nP -i :8790`), занят мостом после запуска
|
||||||
|
7. ⚠️ В дашборде в `services.yaml` **нет** записи `agents_bridge` — добавить в шаге 4
|
||||||
|
(`health.type: http`, `url: http://127.0.0.1:8790/healthz`, `port: 8790`)
|
||||||
|
|
||||||
## Связанные заметки
|
## Связанные заметки
|
||||||
- [[personal/projects/balda/balda-mm-delegation-plan]] — общий план (Фазы 4-5)
|
- [[personal/projects/balda/balda-mm-delegation-plan]] — общий план (Фазы 4-5)
|
||||||
- [[personal/projects/balda/balda-kraken-mm-deploy]] — Фаза 3 (✅)
|
- [[personal/projects/balda/balda-kraken-mm-deploy]] — Фаза 3 (✅)
|
||||||
- [[personal/plans/balda-mm-pr-plan]] — Фаза 2 (PR #8)
|
- [[personal/plans/balda-mm-pr-plan]] — Фаза 2 (PR #8)
|
||||||
|
- [[personal/tech/agents-bridge]] — мост :8790, API, питфоллы (шаг 2 ✅)
|
||||||
- [[personal/tech/macos-docker-virtiofs-mount-limits]] — ограничения macOS Docker
|
- [[personal/tech/macos-docker-virtiofs-mount-limits]] — ограничения macOS Docker
|
||||||
- [[personal/tech/balda-go-fx-pitfalls]] — fx-питфоллы, дельта-апплаер
|
- [[personal/tech/balda-go-fx-pitfalls]] — fx-питфоллы, дельта-апплаер
|
||||||
- [[family/how-to/kraken-portainer-access]] — cloudflared, routes
|
- [[family/how-to/kraken-portainer-access]] — cloudflared, routes
|
||||||
|
|||||||
@@ -20,6 +20,74 @@ updated: '2026-09-26'
|
|||||||
| [[2-medium-confidence\|Средняя уверенность]] | 5813 |
|
| [[2-medium-confidence\|Средняя уверенность]] | 5813 |
|
||||||
| [[3-high-confidence\|Высокая уверенность]] | 959 |
|
| [[3-high-confidence\|Высокая уверенность]] | 959 |
|
||||||
|
|
||||||
|
## 🔴 Пятнадцатая волна (2026-09-26): КЛАСС 3 ЗАКРЫТ, КЛАСС 4 НАЧАТ
|
||||||
|
|
||||||
|
### ✅ Класс 3 (номер трека в `new_title`) — ЗАКРЫТ ПОЛНОСТЬЮ, 156 строк
|
||||||
|
|
||||||
|
Блок `!Детские/Детский хит/` доведён до конца. Фильтр остатка → **пусто**:
|
||||||
|
`grep 'Детский хит/' tag-fix-plan.csv | grep 'artist<-cleared-junk'`.
|
||||||
|
|
||||||
|
Паттерн фикса (единый):
|
||||||
|
|
||||||
|
```
|
||||||
|
БЫЛО: title = `143 БЮРО НАХОДОК`, artist = (пусто), track = (пусто), source = artist<-cleared-junk
|
||||||
|
СТАЛО: title = `БЮРО НАХОДОК`, artist = (пусто), track = 143, source = manual (user decision)
|
||||||
|
```
|
||||||
|
|
||||||
|
**artist пустой намеренно** — сборник детских песен из мультфильмов без единого исполнителя.
|
||||||
|
`album = Детский Хит Сезона` — название сборника, **остаётся**.
|
||||||
|
|
||||||
|
Полный список исправленного — в `personal/tech/music-tags-repair-truenas.md`, раздел «ПЯТНАДЦАТАЯ ВОЛНА».
|
||||||
|
|
||||||
|
### ⚠️ Ложные срабатывания детектора «номер в title»
|
||||||
|
|
||||||
|
`grep -E ',[0-9]{1,3} [А-ЯЁA-Z]'` ловит **нормальные** названия:
|
||||||
|
`32 Leaves` (группа), `3 Doors Down` (группа), `2 кота` (часть названия),
|
||||||
|
`Зинчук` (номер в **пути**, папка диска), `Амадеус N 146 2002` (номер альбома).
|
||||||
|
|
||||||
|
> 🔴 **Правило: цифра в title — НЕ автоматически дефект.** Номер трека стоит **в начале** title
|
||||||
|
> через пробел и дублируется как `NNN_` в имени файла. Разбирать 3-5 примеров глазами до
|
||||||
|
> объявления классом.
|
||||||
|
|
||||||
|
### 🔄 Класс 4 (транслит) — ~20 из ~40
|
||||||
|
|
||||||
|
Метка `translit artist tag; folder is Cyrillic` = **116 строк**, но большинство **ложные**
|
||||||
|
(западные группы: Joe Hisaishi, Ian Oliver, Yello, Muse, Gorillaz, Europe, Pain, Scooter).
|
||||||
|
**Реальные — русские группы латиницей.**
|
||||||
|
|
||||||
|
Исправлено: `!A Not sorted/Sbornik_Novij_Rok` (13 строк: Мумий Тролль, Мара, Дельфин, Фактор Страха,
|
||||||
|
Гроза, Диверсанты, Курара, Лакмус, Смысловые Галлюцинации, Скрябин, Бумбокс, Декабрь, Бумбокс),
|
||||||
|
Глюкоза, Потап и Настя Каменских, Каста (`Бабка`, `Горячее время`), **Наутилус Помпилиус**
|
||||||
|
(альбомы Атлантида 11, Раскол 10, Подъём 12).
|
||||||
|
|
||||||
|
### 🔴 Три собственные ошибки, пойманные в diff
|
||||||
|
|
||||||
|
1. `Берегитесь, мальчики` — запятая без кавычек → строка распалась на лишние колонки.
|
||||||
|
2. В «Крепкий орешек» подставил title `Дождь`.
|
||||||
|
3. `Goryacheye Vremya` приписал artist `Баста` вместо `Каста`.
|
||||||
|
|
||||||
|
> **Правило: читать diff после каждой правки `patch`.** Все три были видны именно в diff.
|
||||||
|
|
||||||
|
### 📊 Состояние
|
||||||
|
|
||||||
|
| Показатель | Значение |
|
||||||
|
|---|---:|
|
||||||
|
| Битых строк | **0** |
|
||||||
|
| Ручных правок | **~500** |
|
||||||
|
| Класс 5/C «склейка в title» | ✅ ЗАКРЫТ |
|
||||||
|
| Класс A «техпапка в artist» | ✅ ЗАКРЫТ |
|
||||||
|
| Класс 3 «номер в title» | ✅ ЗАКРЫТ (156) |
|
||||||
|
| Класс 4 «транслит» | 🔄 ~20 / ~40 |
|
||||||
|
| `no_change` (~1100) | 🔴 НЕ ПРОВЕРЯЛИСЬ |
|
||||||
|
| Применение на NAS | НЕ начато |
|
||||||
|
|
||||||
|
### ⏭ Осталось
|
||||||
|
|
||||||
|
1. **Класс 4** — остаток Наутилуса (`1998 Яблокитай` и далее), `!Рэп/НТЛ` (`RacinG_Portal`,
|
||||||
|
`PaDoNkÈ[NTL]`, `Fristaile`), `Df1` (вероятно НЕ трогать — западные).
|
||||||
|
2. **Строки `no_change` (~1100) — последний непроверенный пласт.**
|
||||||
|
3. Затем бэкап в `Music/backup/` и применение (по «go» Alex) → приёмка в UI → Music-библиотека.
|
||||||
|
|
||||||
## 🔴 Четырнадцатая волна (2026-09-26): КЛАСС A ЗАКРЫТ, КЛАСС 3 НАЧАТ
|
## 🔴 Четырнадцатая волна (2026-09-26): КЛАСС A ЗАКРЫТ, КЛАСС 3 НАЧАТ
|
||||||
|
|
||||||
### ✅ Класс A («имя техпапки в artist/album») закрыт полностью — 0 остатков
|
### ✅ Класс A («имя техпапки в artist/album») закрыт полностью — 0 остатков
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
# agents-bridge — мост Mac ↔ Kraken (FastAPI :8790)
|
||||||
|
|
||||||
|
> Создан 2026-09-26. Компонент Фазы 4 [[personal/plans/balda-mm-phase4-agents]] (шаг 2 ✅).
|
||||||
|
> Назначение: принять задачу от оркестратора Балды (Kraken) по HTTP, запустить
|
||||||
|
> CLI-исполнитель в контейнере `balda-executor`, вернуть вывод.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Расположение
|
||||||
|
|
||||||
|
| Что | Путь |
|
||||||
|
|---|---|
|
||||||
|
| Проект | `~/Developer/agents-bridge/` |
|
||||||
|
| Python | `~/Developer/eagle-dash/.venv/bin/python` (3.14, fastapi 0.115.0, uvicorn 0.30.6) |
|
||||||
|
| Конфиг + секрет | `~/Developer/agents-bridge/.env` (**0600, не коммитить**) |
|
||||||
|
| Шаблон | `~/Developer/agents-bridge/.env.example` |
|
||||||
|
| Состояние | `~/Developer/agents-bridge/state.sqlite3` (WAL) |
|
||||||
|
| Лог (ручной запуск) | `/tmp/agents-bridge.log` |
|
||||||
|
| Контейнер-исполнитель | `balda-executor` (`~/Docker/balda-executor/`) |
|
||||||
|
|
||||||
|
Своего venv у проекта **нет** — используется venv дашборда (там уже fastapi/uvicorn/httpx).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Файлы
|
||||||
|
|
||||||
|
| Файл | Роль |
|
||||||
|
|---|---|
|
||||||
|
| `app.py` | роуты, проверка секрета, лимит параллельности, `ThreadPoolExecutor` |
|
||||||
|
| `store.py` | SQLite: таблица `tasks`, UNIQUE-индекс по `idempotency_key`, `reap_stale()` |
|
||||||
|
| `executor.py` | `docker exec` в контейнер; провайдеры `claude`/`codex`; таймаут; обрезка вывода |
|
||||||
|
| `config.py` | чтение `.env` встроенным парсером + `Settings` (frozen dataclass) |
|
||||||
|
| `requirements.txt` | fastapi==0.115.0, uvicorn==0.30.6, httpx, python-dotenv |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /healthz → статус моста и контейнера (без секрета)
|
||||||
|
POST /task → 202 | 200 (идемпотентный повтор) | 401 | 429 | 400
|
||||||
|
GET /task/{task_id} → статус + stdout/stderr/exit_code
|
||||||
|
GET /tasks?limit=N → последние задачи (для дашборда/отладки)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Авторизация:** заголовок `X-Bridge-Secret` на всех `/task*`. Если `BRIDGE_SECRET` не
|
||||||
|
настроен — `POST /task` возвращает **503**, мост не принимает задачи.
|
||||||
|
|
||||||
|
**Идемпотентность:** заголовок `Idempotency-Key`. Повтор возвращает **тот же** `task_id`
|
||||||
|
с HTTP **200** (первый ответ — 202). Гарантия на уровне БД: UNIQUE-индекс + `IntegrityError`
|
||||||
|
как обработка гонки. CLI запускается **ровно один раз** на задачу.
|
||||||
|
|
||||||
|
**Лимит параллельности:** `MAX_CONCURRENT_TASKS` (по умолчанию **1**). При исчерпании —
|
||||||
|
**429**. Больше 2 задач под одним подписочным аккаунтом — риск бана за «unusual traffic».
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Провайдеры
|
||||||
|
|
||||||
|
`executor.PROVIDERS` — argv для headless-запуска:
|
||||||
|
|
||||||
|
| Провайдер | argv |
|
||||||
|
|---|---|
|
||||||
|
| `claude` | `claude -p --output-format text <prompt>` |
|
||||||
|
| `codex` | `codex exec --skip-git-repo-check <prompt>` |
|
||||||
|
|
||||||
|
Дефолт — `EXECUTOR_PROVIDER=claude`. Команда собирается **списком аргументов** (без
|
||||||
|
`shell=True`), `WORKDIR=/agents` внутри контейнера — наружу не выйти.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Переменные окружения
|
||||||
|
|
||||||
|
| Ключ | Дефолт | Смысл |
|
||||||
|
|---|---|---|
|
||||||
|
| `BRIDGE_HOST` | `127.0.0.1` | слушать только локально (наружу — через туннель) |
|
||||||
|
| `BRIDGE_PORT` | `8790` | порт |
|
||||||
|
| `BRIDGE_SECRET` | — | **обязателен**, 64 симв. `secrets.token_urlsafe(48)` |
|
||||||
|
| `EXECUTOR_CONTAINER` | `balda-executor` | имя контейнера |
|
||||||
|
| `EXECUTOR_PROVIDER` | `claude` | `claude` или `codex` |
|
||||||
|
| `MAX_CONCURRENT_TASKS` | `1` | одновременно выполняемых |
|
||||||
|
| `TASK_TIMEOUT_SECONDS` | `900` | таймаут задачи, процесс убивается |
|
||||||
|
| `MAX_OUTPUT_BYTES` | `200000` | вывод обрезается |
|
||||||
|
| `DB_PATH` | `state.sqlite3` | SQLite |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Запуск
|
||||||
|
|
||||||
|
**Сейчас — вручную** (launchd ещё не сделан, см. открытый пункт 4 плана):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/Developer/agents-bridge
|
||||||
|
~/Developer/eagle-dash/.venv/bin/python -m uvicorn app:app --host 127.0.0.1 --port 8790
|
||||||
|
```
|
||||||
|
|
||||||
|
Проверка:
|
||||||
|
```bash
|
||||||
|
curl -s http://127.0.0.1:8790/healthz
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ На macOS `docker compose` **не работает** — только `docker-compose` (см. план, шаг 1).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Питфоллы
|
||||||
|
|
||||||
|
### 1. `Not logged in` — это ответ CLI, а не ошибка моста
|
||||||
|
|
||||||
|
Сквозная проба до логина CLI вернула:
|
||||||
|
```
|
||||||
|
status=failed exit_code=1 stdout='Not logged in · Please run /login'
|
||||||
|
```
|
||||||
|
Это **признак рабочего конвейера**: docker поднял процесс, `claude` ответил. Если видишь
|
||||||
|
эту строку — auth у исполнителя, а не мост. Логин делает **Alex сам**; копирование
|
||||||
|
auth-файлов из `~/.claude`/`~/.codex` отклонено, не предлагать.
|
||||||
|
|
||||||
|
### 2. Редакция секретов Hermes искажает команды создания `.env`
|
||||||
|
|
||||||
|
`python -c` с f-строкой `BRIDGE_SECRET={s}` печатает в лог обрезанный фрагмент
|
||||||
|
(`E...cret written`) — **редакция Hermes, файл на диске цел**. Не «чинить».
|
||||||
|
|
||||||
|
Проверять `.env` только так:
|
||||||
|
```bash
|
||||||
|
/usr/bin/awk -F= '{ if ($1 ~ /SECRET|TOKEN|KEY|PASSWORD/) print $1"=<redacted len "length($2)">"; else print }' .env
|
||||||
|
```
|
||||||
|
`read_file` на `.env` отказывает по определению (secret-bearing file) — это норма.
|
||||||
|
|
||||||
|
### 3. Зависшие задачи после рестарта
|
||||||
|
|
||||||
|
`store.reap_stale()` на старте помечает `running`-задачи старше `TASK_TIMEOUT_SECONDS`
|
||||||
|
как `timeout` с причиной `bridge restarted while task was running`. Иначе они навсегда
|
||||||
|
висят активными и блокируют слот лимита.
|
||||||
|
|
||||||
|
### 4. Мост не переживает перезагрузку
|
||||||
|
|
||||||
|
Пока нет launchd-плейта `com.agents.bridge`, процесс живёт только в текущей сессии.
|
||||||
|
Это **блокер для шага 3** (туннель опубликует URL, ведущий в закрытый порт).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Порядок ручной приёмки (сработавший)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -o /dev/null -w "%{http_code}\n" -X POST http://127.0.0.1:8790/task \
|
||||||
|
-H 'Content-Type: application/json' -d '{"prompt":"hi"}' # → 401 (нет секрета)
|
||||||
|
|
||||||
|
# с секретом и одним Idempotency-Key дважды → один и тот же task_id, 202 затем 200
|
||||||
|
# GET /task/{id} → status/stdout/exit_code
|
||||||
|
```
|
||||||
|
|
||||||
|
Тестовый скрипт: `/tmp/test-bridge.sh` (читает секрет из `.env`, в командной строке
|
||||||
|
секрет не светится).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Связанное
|
||||||
|
|
||||||
|
- [[personal/plans/balda-mm-phase4-agents]] — план Фазы 4 (шаги 1-2 ✅)
|
||||||
|
- [[personal/tech/macos-docker-virtiofs-mount-limits]] — почему bind-mount вместо symlink
|
||||||
|
- [[personal/projects/balda/balda-mm-delegation-plan]] — общий план делегирования
|
||||||
|
|
||||||
|
## История
|
||||||
|
- **2026-09-26**: создан, поднят на :8790, протестирован (auth 401, идемпотентность,
|
||||||
|
сквозной вызов CLI). Не в launchd. Логин CLI — за Alex.
|
||||||
@@ -4,6 +4,7 @@ created: '2026-09-26'
|
|||||||
updated: '2026-09-26'
|
updated: '2026-09-26'
|
||||||
type: tech
|
type: tech
|
||||||
namespace: personal
|
namespace: personal
|
||||||
|
wave: 15
|
||||||
tags:
|
tags:
|
||||||
- music
|
- music
|
||||||
- jellyfin
|
- jellyfin
|
||||||
@@ -19,14 +20,19 @@ related:
|
|||||||
|
|
||||||
# Music Tags Repair — TrueNAS (7906 файлов)
|
# Music Tags Repair — TrueNAS (7906 файлов)
|
||||||
|
|
||||||
> **Статус: ЧЕТЫРНАДЦАТАЯ ВОЛНА (2026-09-26). КЛАСС C (склейка) И КЛАСС A (техпапка) ЗАКРЫТЫ.
|
> **Статус: ПЯТНАДЦАТАЯ ВОЛНА (2026-09-26). КЛАСС C, КЛАСС A, КЛАСС 3 — ЗАКРЫТЫ ПОЛНОСТЬЮ.
|
||||||
> КЛАСС 3 (номер в title) — В РАБОТЕ (~25 из ~80). NAS ДОСТУПЕН, применение НЕ начато.**
|
> КЛАСС 4 (транслит) — В РАБОТЕ (~20 из ~40). NAS ДОСТУПЕН, применение НЕ начато.**
|
||||||
> Работа — ручной проход по CSV `tag-fix-plan.csv` построчно; правка скриптов ЗАПРЕЩЕНА.**
|
> Работа — ручной проход по CSV `tag-fix-plan.csv` построчно; правка скриптов ЗАПРЕЩЕНА.**
|
||||||
> ✅ **Класс A («имя техпапки в artist/album») — ЗАКРЫТ ПОЛНОСТЬЮ: 0 остатков.**
|
> ✅ **Класс A («имя техпапки в artist/album») — ЗАКРЫТ ПОЛНОСТЬЮ: 0 остатков.**
|
||||||
> (`Забугр`, `disk`, `disk_v2`, `1 DRIVE`, `5 POPSA`, `3 SHANSON` — все вычищены.)
|
> (`Забугр`, `disk`, `disk_v2`, `1 DRIVE`, `5 POPSA`, `3 SHANSON` — все вычищены.)
|
||||||
> ✅ **Класс 3 (номер трека в `new_title`) — в работе: блок `!Детские/Детский хит` ~25 из ~80.**
|
> ✅ **Класс 3 (номер трека в `new_title`) — ЗАКРЫТ ПОЛНОСТЬЮ.** Блок `!Детские/Детский хит/`
|
||||||
> ❌ Осталось: класс 3 (~55 строк), транслит (~40), строки с `no_change` (~1100, не проверялись).
|
> — все **156 строк**: номер → `new_track`, title чистый, artist пустой, album `Детский Хит Сезона`.
|
||||||
> Детали и таблицы — «ЧЕТЫРНАДЦАТАЯ ВОЛНА».
|
> ✅ **Класс 4 (транслит) — в работе: ~20 из ~40.** Закрыты: `!A Not sorted/Sbornik_Novij_Rok`
|
||||||
|
> (10 строк), Мумий Тролль, Мара, Дельфин, Каста, Глюкоза, Потап и Настя, Наутилус Помпилиус
|
||||||
|
> (альбомы Атлантида / Раскол / Подъём).
|
||||||
|
> ❌ Осталось: транслит Наутилуса (`Яблокитай` и далее), строки с `no_change` (~1100, не проверялись),
|
||||||
|
> транслит в `!Рэп/НТЛ`, `Df1`.
|
||||||
|
> Детали и таблицы — «ПЯТНАДЦАТАЯ ВОЛНА».
|
||||||
> ✅ **Проверка целостности (быстрая, без python):**
|
> ✅ **Проверка целостности (быстрая, без python):**
|
||||||
> `/usr/bin/awk -F'"' 'NR>1 && NF%2==0 {print NR": "NF}' tag-fix-plan.csv` → пусто = 0 битых.
|
> `/usr/bin/awk -F'"' 'NR>1 && NF%2==0 {print NR": "NF}' tag-fix-plan.csv` → пусто = 0 битых.
|
||||||
> **CSV: 7907 строк (7906 данных + заголовок), 0 битых. Ручных правок: 311+.**
|
> **CSV: 7907 строк (7906 данных + заголовок), 0 битых. Ручных правок: 311+.**
|
||||||
@@ -64,6 +70,167 @@ related:
|
|||||||
> Прогонялись **девять волн** проверок: см. таблицу волн ниже.
|
> Прогонялись **девять волн** проверок: см. таблицу волн ниже.
|
||||||
> Итог v7: «требует решения» **4**, medium **5811**, high **958**, mojibake = 0, остаточный mojibake = 0.
|
> Итог v7: «требует решения» **4**, medium **5811**, high **958**, mojibake = 0, остаточный mojibake = 0.
|
||||||
|
|
||||||
|
## 🖐 ПЯТНАДЦАТАЯ ВОЛНА: КЛАСС 3 ЗАКРЫТ, КЛАСС 4 НАЧАТ (2026-09-26)
|
||||||
|
|
||||||
|
### ✅ КЛАСС 3 (номер трека в `new_title`) — ЗАКРЫТ ПОЛНОСТЬЮ (156 строк)
|
||||||
|
|
||||||
|
Блок `!Детские/Детский хит/` — **все строки** доведены до конца.
|
||||||
|
Паттерн фикса (единый для всего блока):
|
||||||
|
|
||||||
|
```
|
||||||
|
БЫЛО: title = `143 БЮРО НАХОДОК`, artist = (пусто), track = (пусто), source = artist<-cleared-junk
|
||||||
|
СТАЛО: title = `БЮРО НАХОДОК`, artist = (пусто), track = 143, source = manual (user decision)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Почему artist пустой:** это сборник детских песен из мультфильмов, у него нет единого
|
||||||
|
исполнителя. `album = Детский Хит Сезона` — осмысленное название сборника, **остаётся**.
|
||||||
|
|
||||||
|
Второй подпаттерн в блоке (строки, где номер уже был убран ранее):
|
||||||
|
`source = track<-filename;artist<-cleared-junk` → просто менялся `source` на
|
||||||
|
`manual (user decision)`, поля уже были верные.
|
||||||
|
|
||||||
|
**Примеры правок (все 156):** НЕ ХОДИТЕ В АФРИКУ (128), РАССКАЖИ СНЕГУРОЧКА (105),
|
||||||
|
МАРИЯ МИРАБЕЛЛА (123), ПЕСЕНКА БОБРЯТ (154), ЧЕБУРАШКА (140), ПЕСНЯ ШАПОКЛЯК (132),
|
||||||
|
ЧЕМУ УЧАТ В ШКОЛЕ (109), ХЭППИ ЭНД (156), АНТОШКА (145), ПЕСНЯ ВОЛКА (103),
|
||||||
|
ПЕСЕНКА БЕЛЯНКИ (135), ПЕСЕНКА ЦАРЯ (155), ПЕСЕНКА ПАРОВОЗИКА (126),
|
||||||
|
ПЕСНЯ ПРО КОНДИТЕРСКУЮ ФАБРИКУ (114), ЛЕСНОЙ ОЛЕНЬ (152), ФИЛЬМ ФИЛЬМ ФИЛЬМ (116),
|
||||||
|
Я ВОДЯНОЙ (106), ПЕСНЯ СИНЕГЛАЗКИ (147), ПЕСНЯ ПИРАТА (108), ПЕСНЯ КОТА (113),
|
||||||
|
КТО ХОДИТ В ГОСТИ ПО УТРАМ (139), ТРИ БЕЛЫХ КОНЯ (124), ПЕСНЯ УРРИ (30),
|
||||||
|
ПЕРВОКЛАШКА (51), ПЕСНЯ ПРИВИДЕНИЙ (88), ПРИХОДИ СКАЗКА (97), КРЫЛАТЫЕ КАЧЕЛИ (89),
|
||||||
|
ПЕСЕНКА О ЖИРАФЕ (33), БАРМАЛЕЙ (71), ПЕСНЯ КОЩЕЯ (40), КРУЧУ КРУЧУ КРУЧУ ПЕДАЛИ КРУЧУ (56),
|
||||||
|
ПРЕКРАСНОЕ ДАЛЕКО (7), МОЖЕТ БЫТЬ ВОРОНА (8), ПЕСЕНКА ХОМЫ И СУСЛИКА (99),
|
||||||
|
ЛЯГУШАЧЬЯ ЛАМБАДА (16), ПЕСНЯ КЛЫКА-ПОТРОШИТЕЛЯ (91), КОЛЫБЕЛЬНАЯ МЕДВЕДИЦЫ (41),
|
||||||
|
ОБЖОРЫ (68), ТОЧКА ТОЧКА ЗАПЯТАЯ (3), ПЕСЕНКА ВАСИЛИСЫ (39), ПЕСНЯ СОЛДАТА (38),
|
||||||
|
БОЛЬШОЙ СЕКРЕТ ДЛЯ МАЛЕНЬКОЙ КАМПАНИИ (94), ПЕСНЯ О ХОТТАБЫЧЕ (64), ПЕСНЯ БЕЛОЧКИ (35),
|
||||||
|
МАНИ-МАНИ (50), ПЕСЕНКА КВАКИ (23), ПЕСНЯ БАБЫ-ЯГИ (118), ПЕСНЯ БАРСУКА БОНИФАЦИЯ (54),
|
||||||
|
ПЕСЕНКА УМКИ (5), РОМАНС ЧЕРЕПАХИ ТОРТИЛЛЫ (134), ГОВОРЯТ МЫ БЯКИ-БУКИ (75),
|
||||||
|
БУРАТИНО (1), ЧУНГА-ЧАНГА (2), КОГДА МОИ ДРУЗЬЯ СО МНОЙ (59), ТАНЕЦ МАЛЕНЬКИХ УТЯТ (6),
|
||||||
|
СПОР МАШИ И ВИТИ О СКАЗКАХ (53), РЫЖИЙ РЫЖИЙ КОНОПАТЫЙ (77), ПЕСНЯ ПРО РОБИН-ГУДА (43),
|
||||||
|
ОХ РАНО ВСТАЕТ ОХРАНА (9), ЧАСТУШКИ БАБОК-ЕЖЕК (11), БЮРО НАХОДОК (143), ПЕСНЯ СЫЩИКА (151),
|
||||||
|
УТРО НАЧИНАЕТСЯ (149), ЧЕЛОВЕК СОБАКЕ ДРУГ (90), НА ДАЛЕКОЙ АМАЗОНКЕ (37), ПЕСНЯ РУСАЛОЧКИ (61),
|
||||||
|
БАЮ БАЮШКИ БАЮ (18), ПЕСНЯ РЫБЫ-ПИЛЫ (52), ГИМН НЕЗНАЙКИ (17), ПОПУРРИ ИЗ М-Ф БРЕМЕНСКИЕ
|
||||||
|
МУЗЫКАНТЫ (82), А МОЖЕТ БЫТЬ ВОРОНА (133), ПУСТЬ НЕТУ НИ КОЛА И НИ ДВОРА (81),
|
||||||
|
ГДЕ ВОДЯТСЯ ВОЛШЕБНИКИ (141), В МИРЕ МНОГО СКАЗОК (57), ПЕСНЯ ХОМЯКА (127),
|
||||||
|
НЕПРИЯТНОСТЬ ЭТУ МЫ ПЕРЕЖИВЕМ (21), ВМЕСТЕ ВЕСЕЛО ШАГАТЬ (150), ЖИВИ В ВОЛШЕБНОМ ЯЩИЧКЕ (66),
|
||||||
|
ТАКАЯ-СЯКАЯ СБЕЖАЛА ИЗ ДВОРЦА (22), КАБЫ НЕ БЫЛО ЗИМЫ (120), СПИ МОЯ РАДОСТЬ УСНИ (137),
|
||||||
|
ПЕСНЯ ВАНИ-ПЕЧНИКА (148), А Я ТАКОЙ ГОЛОДНЫЙ (73), ДВАЖДЫ ДВА - ЧЕТЫРЕ (4),
|
||||||
|
САМОВАРО-ПАРОВОЗО-ВЕРТОЛЕТ (111), ПЕСЕНКА ЛЬВЕНКА И ЧЕРЕПАХИ (60), ПЕСЕНКА ДРАКОНЧИКА (49),
|
||||||
|
ПЕСНЯ ИОХИМА ЛИСА (104), ПОЙ ВАСЯ (101), И Я ТОГО ЖЕ МНЕНИЯ (86), ПЕСЕНКА ВИННИ-ПУХА (47),
|
||||||
|
КАКОЙ ЧУДЕСНЫЙ ДЕНЬ (131), ПЕСНЯ СОРНЯКОВ (142), ПЕСЕНКА КРОКОДИЛА ГЕНЫ (112),
|
||||||
|
НАСТОЯЩИЙ ДРУГ (15), ПЕСНЯ БАЗИЛИО И АЛИСЫ (85), НИЧЕГО НА СВЕТЕ ЛУЧШЕ НЕТУ (80),
|
||||||
|
ДВОЙКА (65), СОБАКА БЫВАЕТ КУСАЧЕЙ (48), ДВА ВЕСЕЛЫХ ГУСЯ (138), ПО СЕКРЕТУ ВСЕМУ СВЕТУ (146),
|
||||||
|
ПЕСНЯ КАРАБАСА БАРАБАСА (46), ВЕСЕННЯЯ КАПЕЛЬ (117), У ПОНИ ДЛИННАЯ ЧЕЛКА ИЗ НЕЖНОГО ШЕЛКА (79),
|
||||||
|
ДУЭТ ТРУБОДУРА И ПРИНЦЕССЫ (29), В ТРАВЕ СИДЕЛ КУЗНЕЧИК (107), МЫ БАНДИТО-ГАНГСТЕРИТО (12),
|
||||||
|
ПЕСНЯ КОТА МАТВЕЯ (119), ПЕСЕНКА О ЛЕТЕ (70), В ЛЕСУ РОДИЛАСЬ ЕЛОЧКА (14),
|
||||||
|
ДУЭТ ГЛУПОГО КОРОЛЯ И ПРЕКРАСНОЙ ПРИНЦЕССЫ (74), ПЕСЕНКА ПАУЧКА АНАСИ (32), КАРУСЕЛЬ (10),
|
||||||
|
ХВОСТ ЗА ХВОСТ (67), ДА НУЖЕН ОТДЫХ ПАРУСАМ (45), ПЕСЕНКА КОТЕНКА (96), ПЕСЕНКА СТРАХОВ (115),
|
||||||
|
ДИАЛОГ ВОЛКА И КОЗЛЯТ (13), ПОЛЕ ЧУДЕС (130), ВТОРАЯ ПЕСНЯ КОЗЫ (153), ЛОМАТЬ КРУШИТЬ (42),
|
||||||
|
ПЕСНЯ ДУРЕМАРА (92), ПЕСНЯ ЛЕШЕГО (136), СДАЕТСЯ КВАРТИРА С РЕБЕНКОМ (122), ПЕСЕНКА ДРУЗЕЙ (144),
|
||||||
|
ПЕСНЯ ДИКИХ ГИТАР (62), ОБЛАКА (25), ПЕСЕНКА КРАСНОЙ ШАПОЧКИ (121), ЗВЕЗДНАЯ СТРАНА (102),
|
||||||
|
ГОЛУБОЙ ВАГОН (78), КУДА ТЫ ТРОПИНКА МЕНЯ ПРИВЕЛА (63), КОЛЫБЕЛЬНАЯ (58),
|
||||||
|
В КАЖДОМ МАЛЕНЬКОМ РЕБЕНКЕ (19), ПЕСНЯ ПТИЦЕЛОВА БЕНКАНА (129), ПЕСНЯ ВОЛКОВ (84),
|
||||||
|
ОСЬМИНОЖКИ (93), ПЕСЕНКА ПРО НЕПРИЯТНОСТИ (44), ВСЕ МЫ ДЕЛИМ ПОПОЛАМ (100),
|
||||||
|
ПЕСНЯ О ЕЛОЧКЕ (20), ПЕСНЯ МИКРОБУСА (110), ПЕСНЯ КОЗЫ (87), ЗЕМЛЯНИЧНОЕ ВАРЕНЬЕ (125),
|
||||||
|
КОРОБКА С КАРАНДАШАМИ (28), ПЕСНЯ СТАМПА (69).
|
||||||
|
|
||||||
|
**Фильтр остатка (после закрытия = 0):**
|
||||||
|
`grep 'Детский хит/' tag-fix-plan.csv | grep 'artist<-cleared-junk'` → пусто.
|
||||||
|
|
||||||
|
### ⚠️ ВАЖНО: ЛОЖНЫЕ СРАБАТЫВАНИЯ ДЕТЕКТОРА «номер в title»
|
||||||
|
|
||||||
|
`grep -E ',[0-9]{1,3} [А-ЯЁA-Z]'` даёт **ложные** на нормальных названиях:
|
||||||
|
|
||||||
|
| Строка | Почему НЕ баг |
|
||||||
|
|---|---|
|
||||||
|
| `145_32 Leaves - All Is Numb` | `32 Leaves` — название группы |
|
||||||
|
| `189_3 Doors Down - It's Not My Time` | `3 Doors Down` — название группы |
|
||||||
|
| `007_Татьяна Зыкина - 2 кота` | `2 кота` — часть названия песни |
|
||||||
|
| `002 Одинокий в ночи 2002/04 Miks` | `Зинчук` — номер в **пути** (папка диска), title чистый |
|
||||||
|
| `001 Амадеус N 146 2002` | `N 146` — номер альбома в названии |
|
||||||
|
|
||||||
|
> 🔴 **Правило: цифра в title — НЕ автоматически дефект.** Номер трека отличается тем, что
|
||||||
|
> стоит **в начале** title и **отделён пробелом**, а сами данные в файле начинаются с `NNN_`
|
||||||
|
> в имени файла. Перед объявлением классом — разобрать 3-5 примеров глазами (тот же урок,
|
||||||
|
> что с детекторами в одиннадцатой и девятой волнах).
|
||||||
|
|
||||||
|
### 🛠 КЛАСС 4 (транслит) — НАЧАТ, ~20 из ~40
|
||||||
|
|
||||||
|
Метка `translit artist tag; folder is Cyrillic` стоит на **116 строках**, но большинство —
|
||||||
|
**ложные**: для западных групп латиница корректна (Joe Hisaishi, Ian Oliver, Yello, Ace of Base,
|
||||||
|
Muse, Gorillaz, Europe, Pain, Scooter, Nautilus в некоторых альбомах и т.д.).
|
||||||
|
**Реальные кандидаты — русские группы, записанные латиницей.**
|
||||||
|
|
||||||
|
**Исправлено в этой волне:**
|
||||||
|
|
||||||
|
| Файл / было | Стало |
|
||||||
|
|---|---|
|
||||||
|
| `Kontrabandy` / `Mumiy Troll'` | `Контрабанды` / `Мумий Тролль` |
|
||||||
|
| `Ya Popala` / `Mara` | `Я попала` / `Мара` |
|
||||||
|
| `Na Zare` / `Evgeniy Grishkovec & Bigudi & Renars Kaupers` | `На заре` / `Евгений Гришковец & Бигуди & Ренарс Кауперс` |
|
||||||
|
| `Bez Nas` / `Del'fin` | `Без нас` / `Дельфин` |
|
||||||
|
| `Vyshe Sil` / `Faktor Straha` | `Выше сил` / `Фактор Страха` |
|
||||||
|
| `Nad Eniseem` / `Groza` | `Над Енисеем` / `Гроза` |
|
||||||
|
| `Beregites' Mal'chiki` / `Diversanty` | `Берегитесь мальчики` / `Диверсанты` |
|
||||||
|
| `Nas Dvoe` / `Kurara` | `Нас двое` / `Курара` |
|
||||||
|
| `My Vstretimsya Tam` / `Lakmus` | `Мы встретимся там` / `Лакмус` |
|
||||||
|
| `Parni Ne Plachut` / `Smyslovye Gallyucinacii` | `Парни не плачут` / `Смысловые Галлюцинации` |
|
||||||
|
| `Fantastika` / `Mumiy Troll'` | `Фантастика` / `Мумий Тролль` |
|
||||||
|
| `Mumitrol'` / `Skryabin` | `Мумитроль` / `Скрябин` |
|
||||||
|
| `Ta Chto` / `Bumboks` | `Та что` / `Бумбокс` |
|
||||||
|
| `PIPEC` / `GLJUKOZA` | `Пипец` / `Глюкоза` |
|
||||||
|
| `Mama, My Vse Soshli S Uma` / `Dekabr'` | `Мама, мы все сошли с ума` / `Декабрь` |
|
||||||
|
| `Krepkiy Oreshek+++` / `Potap & Nastya Kamenskih` (×2) | `Крепкий орешек` / `Потап и Настя Каменских` |
|
||||||
|
| `babka` / `kasta` | `Бабка` / `Каста` |
|
||||||
|
| `Goryacheye Vremya` / `kasta` | `Горячее время` / `Каста` |
|
||||||
|
| `Nautilus Pompilius` → **`Наутилус Помпилиус`** | альбомы **Атлантида** (11), **Раскол** (10), **Подъём** (12) |
|
||||||
|
|
||||||
|
**Папка `!A Not sorted/Sbornik_Novij_Rok`** дала основной улов транслита (13 строк) —
|
||||||
|
там собраны русские рок-группы, у которых теги были латиницей.
|
||||||
|
|
||||||
|
> ⚠️ **Питфолл метода:** `replace_all` по паре `,Nautilus Pompilius,<album>,,no_change,translit artist tag; folder is Cyrillic`
|
||||||
|
> безопасен только при точном указании альбома — иначе `Found 3 matches`. Наутилус правился
|
||||||
|
> по альбомам отдельно (Атлантида, Раскол, Подъём).
|
||||||
|
> **Остаток:** `1998 Яблокитай` и далее — там метка ещё стоит.
|
||||||
|
|
||||||
|
### 🔴 ТРИ СОБСТВЕННЫЕ ОШИБКИ, ПОЙМАННЫЕ И ИСПРАВЛЕННЫЕ В ЭТОЙ ВОЛНЕ
|
||||||
|
|
||||||
|
| # | Ошибка | Как поймано | Фикс |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | `,Берегитесь, мальчики,Диверсанты` — запятая в title без кавычек → строка распалась на лишние колонки | diff показал сдвиг полей | переписал без запятой: `Берегитесь мальчики` |
|
||||||
|
| 2 | В строку «Крепкий орешек» подставил title `Дождь` (не то название) | визуальная проверка diff | вернул `Крепкий орешек` |
|
||||||
|
| 3 | `Goryacheye Vremya` приписал artist `Баста` вместо `Каста` | визуальная проверка diff | `Горячее время` / `Каста` |
|
||||||
|
|
||||||
|
> 🔴 **Правило (закрепить):** после КАЖДОЙ правки читать diff в ответе `patch` — три ошибки
|
||||||
|
> этой волны были видны именно в diff. Значение с запятой внутри **обязательно** в кавычках.
|
||||||
|
|
||||||
|
### 📊 СОСТОЯНИЕ НА КОНЕЦ ПЯТНАДЦАТОЙ ВОЛНЫ
|
||||||
|
|
||||||
|
| Показатель | Значение |
|
||||||
|
|---|---:|
|
||||||
|
| Строк в CSV | 7906 (+1 заголовок = 7907 в файле) |
|
||||||
|
| Битых строк | **0** |
|
||||||
|
| Ручных правок (`source = manual (user decision)`) | **~500** |
|
||||||
|
| Класс C «склейка artist-title в `new_title`» | ✅ **ЗАКРЫТ** |
|
||||||
|
| Класс A «имя техпапки в artist/album» | ✅ **ЗАКРЫТ (0 остатков)** |
|
||||||
|
| Класс 3 «номер трека в title» | ✅ **ЗАКРЫТ (156 строк блока `Детский хит`)** |
|
||||||
|
| Класс 4 «транслит вместо русского» | 🔄 **~20 / ~40** |
|
||||||
|
| Строки `no_change` (~1100) | 🔴 **НЕ ПРОВЕРЯЛИСЬ** |
|
||||||
|
| Применение на NAS | **НЕ начато** |
|
||||||
|
|
||||||
|
### ⏭ ЧТО ДЕЛАТЬ ПЕРВЫМ ДЕЛОМ В СЛЕДУЮЩЕЙ СЕССИИ
|
||||||
|
|
||||||
|
1. **Класс 4, остаток** — транслит Наутилуса (`/!Rock&Folk/Наутилус Помпилиус/1998 Яблокитай/`
|
||||||
|
и следующие альбомы). Детектор: `grep 'translit artist tag'` → отсеять западные группы
|
||||||
|
глазами → править русские.
|
||||||
|
2. **Транслит в `!Рэп/НТЛ`** — `RacinG_Portal` / artist `PaDoNkÈ[NTL]` (стр. 2823), `Fristaile`,
|
||||||
|
`DrakRacing`, `Kasta - Kto budet pit' s nami` → русский.
|
||||||
|
3. **Транслит в `Df1`** — проверить глазами, там в основном западные (Paffendorf, Ian Oliver) —
|
||||||
|
вероятно НЕ трогать.
|
||||||
|
4. **Проверить строки `no_change`** (~1100) — часть заведомо грязная (David Guetta был вытащен
|
||||||
|
вручную). Это последний непроверенный пласт.
|
||||||
|
5. Только после этого — **бэкап в `Music/backup/` и применение** (по «go» Alex), затем приёмка
|
||||||
|
в UI, затем Music-библиотека Jellyfin.
|
||||||
|
|
||||||
## 🖐 ЧЕТЫРНАДЦАТАЯ ВОЛНА: КЛАСС A ЗАКРЫТ + КЛАСС 3 НАЧАТ (2026-09-26)
|
## 🖐 ЧЕТЫРНАДЦАТАЯ ВОЛНА: КЛАСС A ЗАКРЫТ + КЛАСС 3 НАЧАТ (2026-09-26)
|
||||||
|
|
||||||
### 🔴 ГЛАВНЫЙ УРОК ВОЛНЫ: `awk -F','` НЕ ГОДИТСЯ И ДЛЯ ДЕТЕКТА ПОЛЕЙ — ТОЛЬКО ДЛЯ КАВЫЧЕК
|
### 🔴 ГЛАВНЫЙ УРОК ВОЛНЫ: `awk -F','` НЕ ГОДИТСЯ И ДЛЯ ДЕТЕКТА ПОЛЕЙ — ТОЛЬКО ДЛЯ КАВЫЧЕК
|
||||||
|
|||||||
Reference in new issue
Block a user