Добавлен раздел P0-0: правка _finish уже в main (7090c8a), её нельзя
потерять при слиянии. Там же второй дефект того же класса —
splash.py вызывает несуществующий AssetManager.get_splash_logo.
Дефект «вызов несуществующего метода» встречается третий раз и под
pythonw всегда молчаливый, поэтому в критерии приёмки добавлено
требование механической проверки UI-слоя.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
148 lines
14 KiB
Markdown
148 lines
14 KiB
Markdown
# Задание B7 (Codex): дефекты, найденные при живой эксплуатации
|
||
|
||
## Дата поступления
|
||
2026-08-22
|
||
|
||
## База
|
||
Проверочный HEAD на момент выдачи: **`7f912f1`**. Обязательно обновить локальную копию — см. следующий раздел.
|
||
|
||
## Ветка
|
||
`codex/usability-fixes`
|
||
|
||
## Отношение к B6
|
||
Задание **B6 (граф маршрутизации) остаётся в силе**, но это — приоритетнее. Владелец впервые прошёл сценарий вживую, и половина действий не сработала. Сначала чинится то, что он не смог сделать, потом граф.
|
||
|
||
---
|
||
|
||
## Перед началом: обновить локальную копию
|
||
|
||
Задание выдано, когда `origin/main` был `7f912f1`. Ваша рабочая копия на другой машине почти наверняка отстала — за последние сутки в `main` вошло 9 коммитов, включая работу Codex по интерфейсу и принятые задания Antigravity A6–A8.
|
||
|
||
Порядок:
|
||
|
||
```
|
||
cd <каталог репозитория>; git fetch origin --prune; git status
|
||
```
|
||
|
||
Если рабочее дерево чистое:
|
||
|
||
```
|
||
git checkout main; git reset --hard origin/main
|
||
```
|
||
|
||
Если есть незакоммиченные правки — сначала сохранить их отдельной веткой, вслепую сбрасывать нельзя.
|
||
|
||
После обновления **зафиксировать фактический `BASE_SHA`** командой `git rev-parse --short HEAD` и указать его в отчёте. Не считать `7f912f1` актуальным автоматически: пока вы работаете, `main` может уйти вперёд.
|
||
|
||
Ветку создавать **от свежего `origin/main`**, не от старого состояния. Иначе слияние принесёт откат чужой работы — так уже случалось: одна из веток содержала устаревшую распаковку `start_profile_oauth`, и при неаккуратном слиянии подключение Antigravity-аккаунта снова бы сломалось.
|
||
|
||
---
|
||
|
||
|
||
## Что сообщил владелец, дословно
|
||
|
||
1. «завершить не нажимается. пишет что все исчерпано, но нет»
|
||
2. «при тесте открывается опять окно авторизации и ничего»
|
||
3. «появляется код, куда его вставлять, не понятно»
|
||
4. «назначить роль не получается, ничего не видно»
|
||
5. «в маршрутизации при нажатии на кнопку настроить ничего не происходит»
|
||
|
||
Каждое проверено по коду. Ниже — что относится к вам; пункты 1 (частично) и 2 уходят в backend отдельным заданием A8.
|
||
|
||
## P0-0. Уже исправлено на main — не откатите при слиянии
|
||
|
||
Владелец сообщил: «завершить кнопка нажимается, но окно не закрывается». Найдено и исправлено ревьюером в `7090c8a`, файл вашей зоны — `add_account_wizard.py`.
|
||
|
||
Причина: `_finish` первой строкой вызывал `EventLogService.get().log_event(...)`. Метода `log_event` у сервиса **нет** — настоящая сигнатура `log(category, message, details=None, level="info")`. `AttributeError` уходил в обработчик Tk, консоли под `pythonw` нет, и для пользователя кнопка просто не работала: окно оставалось открытым, `on_complete` не вызывался, подключённый аккаунт не попадал в маршрутизацию.
|
||
|
||
Правка: вызов приведён к настоящему API; журналирование и `on_complete` обёрнуты так, чтобы сбой в них не запирал пользователя в мастере. Регрессия закрыта тестом `tests/test_ui_wizard_finish.py`.
|
||
|
||
**От вас требуется:**
|
||
|
||
1. При слиянии сохранить эту правку. Ветку создавать от свежего `origin/main` — тогда конфликта не будет.
|
||
2. Найденный тем же способом второй дефект: `ui/splash.py:40` вызывает `AssetManager.get().get_splash_logo(...)` — такого метода нет, есть `get_logo_image`. Модуль сейчас **нигде не импортируется**, то есть это мёртвый код. Либо подключить и починить, либо удалить. Решение обосновать в отчёте.
|
||
3. **Механическая проверка на весь UI-слой.** Это третий дефект класса «вызов несуществующего метода», и все они молчаливые: под `pythonw` трейсбек Tk уходит в никуда, кнопка выглядит нерабочей. Нужен тест, который статически обходит UI-слой и проверяет, что вызываемые методы существуют у своих классов. Ревьюер проверял разбором AST по образцу `Klass.get().method(...)` — этого хватило, чтобы найти оба дефекта; ваш вариант может быть шире.
|
||
|
||
---
|
||
|
||
## P0-1. «Настроить» в маршрутизации не делает ничего
|
||
|
||
`hermes_hub_app.py:632`:
|
||
|
||
```python
|
||
elif action == "edit_route":
|
||
self._show_toast("Редактор цепочки использует кнопки и селекторы; drag-and-drop отключён.")
|
||
```
|
||
|
||
Кнопка показывает сообщение про отключённый drag-and-drop — и всё. С точки зрения пользователя нажатие не делает ничего, а текст объясняет то, чего он не спрашивал.
|
||
|
||
Требуется настоящий редактор цепочки для роли: список профилей в порядке приоритета, изменение порядка, добавление и удаление профиля из цепочки, сохранение через `AutoAssigner`. Кнопочный и селекторный, без drag-and-drop — это оговорено и допустимо. Но он должен существовать.
|
||
|
||
## P0-2. Результат действия не виден
|
||
|
||
«назначить роль не получается, ничего не видно».
|
||
|
||
Проверил: модальное окно назначения роли **открывается** и содержит семь вариантов — здесь дефекта нет. Проблема в обратной связи: результат уходит в `_show_toast`, то есть в строку состояния внизу окна, где его легко не заметить. Если профиль не найден (а при выборе Claude или Grok он сейчас действительно не найден — см. A8), пользователь видит ровно ничего.
|
||
|
||
Требуется:
|
||
- результат действия показывать заметно: в самой модалке до закрытия либо всплывающим уведомлением рядом с местом действия;
|
||
- **при ошибке модалку не закрывать** — сейчас `modal.destroy()` вызывается до показа результата, и человек остаётся без контекста;
|
||
- то же для остальных действий карточки: «Тест», «Основной», «Оркестратор».
|
||
|
||
## P0-3. Код авторизации: непонятно, что с ним делать
|
||
|
||
«появляется код, куда его вставлять, не понятно».
|
||
|
||
Сейчас в мастере для Codex и Grok показывается поле со ссылкой, отдельная метка с кодом и статус «Ожидание подтверждения кода XXX в браузере…». Ни одной фразы о том, что нужно сделать.
|
||
|
||
Требуется явная пронумерованная последовательность прямо в шаге:
|
||
|
||
```
|
||
1. Откройте ссылку — [кнопка «Открыть в браузере»] [копировать]
|
||
2. Введите на странице код: ABCD-1234 [копировать]
|
||
3. Подтвердите доступ — окно закроется само
|
||
```
|
||
|
||
Код — крупно, моноширинным, с кнопкой копирования. Статус ожидания — ниже, отдельной строкой. Пользователь не должен догадываться о порядке действий.
|
||
|
||
## P0-4. Мастер: честное поведение при отсутствии свободного слота
|
||
|
||
Backend вернёт `None`, когда свободных слотов действительно нет (A8 это чинит). Сейчас мастер подставляет `f"{provider[:3]}-spare-1"` — придуманный идентификатор, который может не существовать:
|
||
|
||
```python
|
||
AutoAssigner.find_free_slot(self.selected_provider) or f"{self.selected_provider[:3]}-spare-1"
|
||
```
|
||
|
||
Требуется: если слот не найден — не выдумывать, а показать понятное объяснение («все слоты этого провайдера заняты, освободите один или удалите неиспользуемый аккаунт») и не давать пройти дальше. Кнопка «Завершить» должна быть либо активной и работающей, либо отключённой с подсказкой почему — но не «нажимается и ничего не происходит».
|
||
|
||
## P1-5. Первый запуск должен вести пользователя
|
||
|
||
Остаётся из B6: на пустой конфигурации «Обзор» показывает «Критическое состояние» и пять `Н/Д` без единой подсказки. Первый экран обязан объяснять следующий шаг и вести к нему.
|
||
|
||
---
|
||
|
||
## Ограничения
|
||
|
||
- Граница: ваша зона — `src/antigravity_provider/router/ui/**`, `hermes_hub_app.py`, `tests/test_ui_*.py`.
|
||
- Не выдумывать идентификаторы, значения и метрики. Нет данных — «Н/Д» либо блок отсутствует.
|
||
- Три темы сохранить.
|
||
- Мастер не ломать: шесть рабочих потоков подключения и трёхэлементная распаковка `start_profile_oauth`.
|
||
- Тег `v0.1.1` не создавать.
|
||
|
||
## Критерии приёмки
|
||
|
||
1. Ни один файл чужой зоны не изменён.
|
||
2. Правка `_finish` из `7090c8a` сохранена; `tests/test_ui_wizard_finish.py` проходит.
|
||
3. Есть тест, механически ловящий вызовы несуществующих методов в UI-слое; на нём проверено, что таких вызовов не осталось.
|
||
4. «Настроить» открывает работающий редактор цепочки; изменение сохраняется и видно после перезапуска.
|
||
5. Ошибка любого действия видна пользователю в месте действия; модалка при ошибке остаётся открытой.
|
||
6. Шаг с кодом устройства содержит пронумерованную инструкцию и кнопки копирования для ссылки и кода.
|
||
7. При отсутствии свободного слота мастер объясняет причину и не подставляет выдуманный идентификатор.
|
||
8. Пустое состояние «Обзора» ведёт к подключению аккаунта.
|
||
9. Тесты на каждый пункт: редактор цепочки сохраняет порядок; ошибка действия отображается; мастер без свободных слотов не завершается молча.
|
||
10. Прогон **в обоих окружениях** — без UI-зависимостей и с `customtkinter`/`pillow`/`psutil`; обе команды и оба результата в отчёте.
|
||
11. `ruff check .` чисто; release gate не ухудшен.
|
||
12. **Скриншоты живого сценария**: подключение аккаунта, назначение роли, редактор цепочки — с реальными данными.
|
||
|
||
## Порядок сдачи
|
||
Передать точный `FINAL_COMMIT_SHA`.
|