hermes-hub/agents/inbox/2026-08-25-A31-preflight-state-batching-pii.md
Hermes Team d6ec34d482 docs(agents): задание A31 — проверка готовности, состояние прогона, батчинг, персональные данные
Владелец передал набор описаний субагентов. Ревьюер сверил каждое с кодом:
большая часть уже реализована в Hermes Hub и сильнее шаблонов. Model Router —
это сам Hub; Retry & Fallback — router_engine с цепочками и порогами квот из
A26; Coordinator в части конфликтов доступа — LeaseManager с max_concurrency,
настраиваемым на профиль. Всё это внесено в задание таблицей «не
реализовывать заново», чтобы к вопросу не возвращались.

В работу вошло только отсутствующее:

- роль «Проверяющий готовность»: проект терял раунды на коде 12 установщика,
  неустановленных fastapi/uvicorn, обязательном --effort и отсутствующем
  ag_slot_oauth.py — всё это выяснялось посреди прогона;
- состояние прогона для workflow из A30, как механика, а не роль;
- ограничение одновременных вызовов и контекст для локальных моделей: на
  сервере владельца два llama.cpp с --parallel 1 и почти исчерпанной памятью;
- маскирование почт: sanitize_snapshot вычищает секреты, но слово email в
  server.py не встречается ни разу, а хаб теперь открыт в домашнюю сеть
  поверх HTTP.

Отдельно зафиксировано для роли контроля затрат: поля токенов в телеметрии
есть, но провайдеры их не отдают, поэтому расход можно только оценивать — и
оценку нельзя выдавать за измерение.

Выполнять после A28, A29 и A30.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 19:26:12 +07:00

171 lines
15 KiB
Markdown
Raw Permalink 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.

# Задание A31: проверка готовности, состояние прогона, батчинг и персональные данные
## Дата поступления
2026-08-25
## База
Проверочный HEAD на момент выдачи: **`1a21c8b`**.
## Ветка
`antigravity/preflight-state-batching`
## Когда выполнять
**После A28, A29 и A30.** Задание дорабатывает то, что они закладывают, и раньше их начинать нельзя: пункты P0-1 и P0-2 опираются на реестр ролей из A28 и на механику workflow из A30.
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-6** написан для аудитора.
---
## Порядок работы с git
```
cd <каталог репозитория>; git fetch origin --prune; git status
git checkout main; git pull --ff-only origin main
git checkout -b antigravity/preflight-state-batching
git commit -m "..." <- сначала коммит
git push -u origin antigravity/preflight-state-batching
```
В `main` напрямую не пушить.
---
## Откуда взялось
Владелец передал набор описаний субагентов (`Скиллы/`, 13 файлов). Ревьюер сверил каждое с текущим кодом. Большая часть уже реализована в Hermes Hub и сильнее шаблонов — их брать не нужно, и это зафиксировано ниже, чтобы к вопросу не возвращались. В задание вошло только то, чего действительно нет.
### Что уже есть — не реализовывать заново
| Шаблон | Что в проекте вместо него |
|---|---|
| Model Router | Сам Hub: `route_request`, цепочки по ролям, обнаружение моделей, `set_model` |
| Retry & Fallback Agent | `router_engine`: цепочки, `max_failover_attempts`, cooldown, здоровье по семействам, пороги квот из A26 |
| Coordinator (конфликты доступа) | `LeaseManager`, `max_concurrency` на профиль — `router_config.py:21`, применяется в `router_engine.py:217` |
| Tool Router | Маршрутизация инструментов — дело Hermes Agent, а не Hub |
| Test Agent | Дублирует роль `tester` из A28 |
| Retriever / Chunker / QA | RAG по базе знаний; Hermes Hub не про это |
| Lyrics-to-Structure, Timing & Pacing, Multimodal Validator | Музыка и озвучка, к продукту отношения не имеют |
---
## P0-1. Роль «Проверяющий готовность» (Dependency Agent)
Тринадцатая роль в реестре A28.
**Обязанности:** до начала задачи убедиться, что на месте всё необходимое — исполняемые файлы и CLI, библиотеки, учётные данные, права доступа, доступность локальных серверов. Сообщить о нехватке **до** запуска, а не посреди прогона.
Обоснование не теоретическое. Проект терял раунды ровно на этом:
- установщик падал с кодом 12, потому что проверочный скрипт был заморожен на 16 профилях;
- веб-сервер не стартовал на Windows: установщик не ставил `fastapi` и `uvicorn`;
- gemini отказывался работать без `--effort`, когда карта моделей была пуста;
- гайд владельца вёл копировать `scripts/ag_slot_oauth.py`, которого нет ни в репозитории, ни в истории git.
Требуется:
1. Роль заведена в реестре с описанием обязанностей, видимым в интерфейсе.
2. Набор проверок реальный и исполняемый: наличие `agy`, `fastapi`, `uvicorn`, доступность настроенных локальных серверов, наличие учётных данных у профилей в цепочках ролей.
3. Результат — **список с причинами**, а не «всё плохо». Каждая непройденная проверка называет, чего именно не хватает и что с этим делать.
4. Проверка не должна ходить в сеть к платным провайдерам и жечь квоту.
## P0-2. Состояние прогона (State Manager)
**Не отдельная роль, а механика внутри workflow из A30.** Заводить агента с таким именем не нужно.
Workflow из A30 идёт итерациями с возвратами на доработку. Прогон может прерваться: сервер перезапустили, обновление установилось, машина ушла в перезагрузку. Сейчас всё это теряется.
Требуется хранить и восстанавливать: какие шаги пройдены, какие результаты получены, номер итерации, какой агент был активен. После перезапуска — либо продолжить, либо честно сказать, что прогон прерван и почему. Молчаливая потеря недопустима.
Осторожно: состояние прогона **не должно** содержать секретов. Смотри P0-4.
## P0-3. Батчинг и контекст для локальных моделей
Дополняет A25, который уже влит: `adapters/local_adapter.py` на месте.
Известное про сервер владельца, снято ревьюером при разведке — заново не выяснять:
```
192.168.1.81 два сервера llama.cpp, оба OpenAI-совместимые
порт 8081 Qwen3.8-27B-Q4_K_M, reasoning on, контекст 65536
порт 8082 Qwen3-4B-Instruct-2507, reasoning off
оба --parallel 1, то есть один запрос за раз
видеокарта Tesla V100-PCIE-32GB, занято 28.7 из 32.7 ГБ
```
`--parallel 1` означает: второй запрос встаёт в очередь. Механизм ограничения у нас есть — `LeaseManager` с `max_concurrency`. Требуется убедиться, что для локальных профилей он выставлен в 1 **из конфигурации**, а не по случайному совпадению с умолчанием, и что при занятом сервере маршрутизация уходит к следующему профилю, а не ждёт.
Дальше — оптимизация: обрезка лишнего контекста под предел модели и объединение мелких запросов, если это не ломает семантику. Память видеокарты почти исчерпана, поэтому осторожность с длиной контекста здесь не абстрактная.
**Не выдумывать пределы.** Длину контекста и предел одновременных запросов берите у сервера через `/v1/models` и настройки профиля, а не подставляйте «разумные» числа.
## P0-4. Персональные данные в снапшоте
Проверено исполнением: `sanitize_snapshot` в `web/server.py` вычищает секреты — `access_token`, `refresh_token`, `api_key`, JWT, `Bearer`. **Почты не маскируются вовсе**: слово `email` в файле не встречается ни разу.
Раньше это было приемлемо: хаб слушал `127.0.0.1`. Сейчас у владельца он **открыт в домашнюю сеть** по `0.0.0.0` с токеном, поверх HTTP. Почты всех подключённых аккаунтов уходят по сети открытым текстом.
Контракт (раздел 3, пункт 4) фиксирует: маскирование — решение владельца, по умолчанию отдаём как есть, потому что интерфейс без опознания аккаунта бесполезен.
Требуется **предложить владельцу выбор, а не решить за него**:
1. Настройка маскирования почт в снапшоте: полностью, частично (`v***@gmail.com`) или как есть.
2. При включённом маскировании интерфейс обязан оставаться пригодным: аккаунты должны различаться между собой.
3. Умолчание обосновать в отчёте.
Секреты маскируются всегда и настройке не подлежат.
## P0-5. Честность агента контроля затрат
Роль `cost-controller` заводится в A28. Здесь — предупреждение, которое ей необходимо, иначе она будет врать.
Проверено: поля `prompt_tokens`, `completion_tokens`, `total_tokens` в `telemetry_service` **существуют**, но провайдеры их **не отдают** — в аналитике владельца стоит «Н/Д (не отдаются)».
Значит расход токенов агент может только **оценивать**. Требуется:
1. Оценка обозначается как оценка. Не выдавать её за измерение.
2. Где провайдер всё же вернул настоящие числа — показывать их отдельно от оценок и помечать.
3. Порог бюджета, построенный на оценке, срабатывает — но владелец должен видеть, что решение принято по оценке.
Это то же правило, что уже дважды спасало проект: отсутствие данных не выдаётся за данные.
## P0-6. Аудит вторым проходом
1. **Выдуманные значения.** Особый риск в P0-3 (пределы контекста) и P0-5 (расход токенов). Ни одного числа, которого не дал провайдер или измерение.
2. **Проверки готовности должны действительно исполняться**, а не возвращать заранее заготовленный успех. Запустить при намеренно сломанном окружении и убедиться, что причина названа верно.
3. **Состояние прогона не содержит секретов** — проверить содержимое отдельно.
4. **Маскирование не ломает интерфейс**: аккаунты остаются различимыми.
5. **Побочные изменения** объяснить.
6. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Десктоп (`router/ui/**`) не трогать.
- Не реализовывать заново то, что перечислено в таблице выше как существующее.
- `State Manager` — механика внутри workflow, а не роль в реестре.
- Действия только через существующий `action_handler`; новые — с правкой `docs/web-api/CONTRACT.md`.
- Правило честности без исключений.
- Тег `v0.1.1` не создавать.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. Роль «Проверяющий готовность» заведена; проверки исполняются по-настоящему; при сломанном окружении названа верная причина — приложить вывод.
3. Прогон workflow переживает перезапуск хаба либо честно сообщает о прерывании с причиной; проверено.
4. Состояние прогона не содержит секретов; проверено отдельно.
5. Для локальных профилей ограничение одновременных вызовов равно 1 и задано конфигурацией; при занятом сервере маршрутизация уходит дальше, а не ждёт; проверено.
6. Пределы контекста берутся у сервера, а не зашиты.
7. Маскирование почт настраивается, умолчание обосновано, аккаунты остаются различимыми.
8. Оценка расхода токенов обозначена как оценка и отличима от измеренных значений.
9. Ни одного выдуманного значения; проверено отдельно.
10. `ruff check .` чисто; релизный гейт не ухудшен.
11. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`.
## Главное
Четыре доработки, каждая закрывает известную боль: прогон падает посреди работы из-за отсутствующей зависимости; длинный workflow теряется при перезапуске; локальные модели встают в очередь; почты уходят по сети открытым текстом.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`. Сдано только после появления коммита в `origin`.