hermes-hub/agents/inbox/2026-08-23-A13-antigravity-pro-contract-stability.md
Hermes Team a18de5d468 docs(tasks): A13 и A14 — оставшийся долг
A13 (Pro): раздел контракта о границе между учётными системами Hub и
Hermes — единственный незакрытый пункт A11; варианты связывания профилей
с ценой каждого; устранение нестабильности набора тестов (шесть корней
Tk дают до семи плавающих ошибок на прогон, мешая отличать настоящую
поломку от шума).

A14 (Flash): два невыполненных пункта A12 — компактные карточки
аккаунтов (accounts_view.py не менялся вообще) и разбор дублирующих
разделов «Провайдеры»/«Квоты» (quotas_view.py не тронут), плюс живые
скриншоты, которых не было.

Принято по A11: пропуск вызова без роли работает — замер 0.10 с без
попыток цепочки; зонд переведён на agy models; выдуманный список
gemini-2.5-* убран; refresh_codex_token появился; source квоты не
опережает данные. Релизный гейт стал зелёным, 7/7.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 15:52:07 +07:00

138 lines
12 KiB
Markdown
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.

# Задание A13 (Antigravity Pro, этот ПК): граница продукта и устойчивость тестов
## Дата поступления
2026-08-23
## База
Проверочный HEAD на момент выдачи: **`9c0da36`**.
## Ветка
`antigravity/contract-stability`
---
## Порядок работы с git
**В начале — обновить локальную копию:**
```
cd <каталог репозитория>; git fetch origin --prune; git status
git checkout main; git pull --ff-only origin main
git checkout -b antigravity/contract-stability
```
**Сразу после первого коммита — отправить ветку:**
```
git push -u origin antigravity/contract-stability
```
**В конце — push и проверка, что он прошёл:**
```
git push origin antigravity/contract-stability
git log --oneline -1 origin/antigravity/contract-stability
```
Последняя команда обязана показать ваш финальный коммит.
**Отдельно и важно.** В прошлый раз работа была выполнена, но осталась незакоммиченной в рабочем каталоге, а в `origin` ушла пустая ветка — она указывала на тот же коммит, что и `main`. Ревьюер обнаружил правки случайно и восстановил их вручную. Инструкция «push ветку сразу» была выполнена буквально, а коммит забыт. **Push без коммита ничего не сохраняет.** Перед отчётом убедитесь, что `git status` показывает чистое дерево, а не список изменённых файлов.
---
## Что принято по A11
Проверено исполнением — работа сделана и работает:
- **Пропуск вызова без роли работает.** Замер на слитом коде: вызов в стиле Hermes без роли уходит вниз за **0.10 секунды**, цепочка не пробуется вовсе. Раньше каждый вызов Hermes шёл как `orchestrator` и тратил попытки на исчерпанную цепочку. Это главный пункт A11, и он закрыт.
- **Зонд обнаружения моделей переведён на `agy models`** вместо разбора ошибки заведомо неверной модели.
- **Выдуманный запасной список `gemini-2.5-*` убран** из адаптера — моделей с такими именами у провайдера нет.
- **`refresh_codex_token` появился** — обновления токена Codex не существовало вовсе.
- **`source` квоты больше не заявляет `provider_api`**, когда ни одна корзина не измерена; применено последовательно к `antigravity` и `opencode-go`.
Замечание по обнаружению моделей: сейчас оно возвращает пустой список, но **не по вине кода**. Проверено прямым вызовом — `agy models` виснет и сам по себе (`rc=124` по таймауту 100 секунд), хотя часом раньше отвечал за 40 секунд. Зонд ведёт себя правильно: отдаёт пусто и сохраняет кэш вместо того, чтобы выдумать список.
**Релизный гейт теперь зелёный, 7/7** — проверка 4 проходит. Она была красной несколько раундов подряд.
Исправлено ревьюером при фиксации: тест `test_opencode_shows_published_limits` закреплял прежнюю семантику `source` и падал после вашей правки. Приведён к честной. Код был прав, тест — нет.
---
## P0-1. Граница между учётными системами Hub и Hermes — единственный незакрытый пункт A11
`docs/UI_STATE_CONTRACT.md` не изменялся. Это тот пункт, ради которого владелец и задал вопрос, решив, что «хаб никак не привязан к гермесу».
Что установлено и должно быть записано:
Hermes ведёт **собственные** профили в каталоге `profiles` своего домашнего каталога:
```
agy-01 … agy-06, worker-fast, worker-research, worker-review,
worker-code, worker-code-2, deepseek
```
и настраивает `delegate_task` отдельно: `max_concurrent_children=3`, `provider=opencode-go`, `model=kimi-k2.7-code`.
Профили Hub — `ag-w1`, `ag-orch-fallback`, `codex-orch`, `opengo-*`, теперь ещё `claude-*` и `grok-*`**другое множество идентификаторов**. Один и тот же аккаунт Google живёт в двух учётных системах под разными именами: у Hermes он `agy-05`, у Hub `ag-w2`.
**Требуется раздел в контракте**, отвечающий на четыре вопроса прямо:
1. Что Hub получает от Hermes на каждом вызове. Перечислить фактически: `task_id`, `turn_id`, `api_request_id`, `session_id`, `platform`, `model`, `provider`, `base_url`, `api_mode`, `api_call_count`. И явно: **роли среди них нет.**
2. Чего Hub не видит: профиль Hermes, которым выполняется вызов; настройки `delegate_task`; состав субагентов.
3. Чем Hub управляет: собственными профилями, цепочками отказоустойчивости, квотами своих аккаунтов.
4. Чем не управляет: ничем из перечисленного в пункте 2.
Без этого интерфейс, показывающий «команду агентов» и роли, вводит владельца в заблуждение — он видит на экране роли, которых Hermes не спрашивает, и разумно ожидает, что настройка роли на что-то влияет.
## P0-2. Варианты связывания профилей Hub и Hermes
**Подготовить варианты с ценой каждого. Решение принимает владелец. Молча не реализовывать.**
Как минимум разобрать три:
1. **Сопоставление по идентичности аккаунта** — email из `id_token`. У Hub он уже извлекается (`extract_jwt_identity` в `profile_manager.py`). Насколько надёжно сопоставляются профили Hermes по тому же признаку? Что делать с профилями без email — `worker-fast`, `deepseek`, ключи OpenCode?
2. **Чтение профилей Hermes как источника** — Hub перестаёт вести свой список и отражает список Hermes. Что при этом теряется: цепочки отказоустойчивости привязаны к профилям Hub, роли тоже.
3. **Явная таблица соответствия** — владелец сам связывает `agy-05` с `ag-w2`. Самое предсказуемое и самое ручное.
По каждому: что становится возможным, что ломается, сколько работы, какие данные владельца затрагиваются. Формат — таблица плюс абзац рекомендации с обоснованием.
## P0-3. Набор тестов нестабилен: семь ошибок на прогон
Полный прогон на `main` даёт **309 passed и до семи ошибок**, причём **ошибки кочуют между файлами от запуска к запуску**: то `test_ui_contract_v11.py`, то `test_ui_mockup_redesign.py`, то `test_oauth_lifecycle.py`. Те же тесты **изолированно проходят**:
```
pytest tests/test_ui_contract_v11.py -> 9 passed
pytest -q -> 4 ERROR в этом же файле
```
Диагноз: исчерпание ресурсов Tk. В наборе **шесть отдельных вызовов `ctk.CTk()`** в пяти файлах, каждый создаёт свой корень интерпретатора Tcl. Сообщение — `TclError: ... This probably means that tk wasn't installed properly`, что к установке отношения не имеет.
Это мешает работе прямо сейчас: **невозможно отличить настоящую поломку от шума.** За последние раунды каждый прогон приходилось перепроверять изолированно, и один раз настоящая поломка была замечена только со второго захода.
**Требуется** один общий корень Tk на весь прогон: фикстура в `tests/conftest.py` с областью видимости `session`, к которой приводятся все UI-тесты; отдельные `ctk.CTk()` в тестовых файлах убираются.
Осторожно: тесты, проверяющие поведение при уничтожении окна (`test_ui_wizard_finish.py` проверяет `winfo_exists() == 0` после `_finish`), должны продолжать работать — уничтожается дочернее окно, а не корень.
**Критерий проверки:** десять полных прогонов подряд без единой ошибки. Не один — десять: дефект плавающий, и единственный зелёный прогон ничего не доказывает.
---
## Ограничения
- Параллельно идёт **A14** (интерфейс). Ваши файлы: `docs/**`, `tests/conftest.py`, `tests/test_ui_*.py` **только в части фикстуры корня Tk**, `src/antigravity_provider/router/**` кроме `ui/`. Не ваши: `router/ui/**` по существу, `installer/**`.
- Правку `2d62d39` и пропуск вызова без роли не откатывать.
- Никаких чисел и идентификаторов без измерения.
- Тег `v0.1.1` не создавать.
## Критерии приёмки
1. Ветка в `origin`, финальный коммит виден через `git log origin/antigravity/contract-stability`, `git status` чист.
2. В контракте есть раздел о границе Hub и Hermes, отвечающий на все четыре вопроса; явно сказано, что роль Hermes не передаёт.
3. Варианты связывания профилей поданы с ценой каждого и рекомендацией; ни один не реализован без решения владельца.
4. Десять полных прогонов `pytest -q` подряд без ошибок; вывод всех десяти в отчёте.
5. Тесты, проверяющие уничтожение окна, продолжают проходить.
6. `ruff check .` чисто; релизный гейт остаётся зелёным (7/7 на момент выдачи задания).
7. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, точный `X passed / Y skipped / Z failed`.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`. **Сдано только после появления коммита в `origin`** — проверьте командой перед отчётом.