# Задание A57: вход в Antigravity через сам agy, а не через сочинённый файл ## Дата поступления 2026-09-01 ## База `origin/main` (`f188a18`). ``` git fetch origin --prune git checkout -b antigravity/a57-agy-native-login origin/main ``` В `main` напрямую не пушить. ## Порядок исполнения Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-8** написан для аудитора. Зона: подключение аккаунтов Antigravity. С A56 (сжатие контекста) не пересекается. --- ## Задача Сейчас хаб проводит вход сам: получает токены по OAuth и **записывает чужой файл учётных данных своим кодом**. Формат этого файла ревьюер восстановил по рабочему профилю владельца и по строкам в бинарнике `agy`. Сегодня это работает. Но `agy` обновляется, и формат может измениться молча: файл останется на месте, вход перестанет засчитываться, а владелец увидит ровно ту необъяснимую картину, которую ловили полдня — «Авторизация успешно завершена» и тут же «Please sign in to view available models». Правильный ответ — дать войти самому `agy`, с `HOME`, указывающим на каталог профиля. Тогда он пишет свои файлы своим форматом, сам обновляет токен по истечении часа, и гадать не о чем. --- ## Что проверено ревьюером — заново не выяснять ### Неинтерактивного входа у agy нет `agy --help` (проверено запуском) даёт подкоманды: `agent`, `agents`, `changelog`, `help`, `install`, `mcp`, `mic-serve`, `models`, `plugin`, `plugins`, `update`. Подкоманд `login` или `auth` **нет**. Вход один: запустить CLI без аргументов и пройти его в терминале. Это же говорит текст ошибки самого agy: ``` Error: Please sign in to view available models. Launch the CLI without arguments to sign in. ``` Искать скрытый флаг входа не надо — его нет. ### Что agy держит в каталоге профиля Рабочий профиль владельца `ag-orch-fallback` (11 моделей): ``` .gemini/oauth_creds.json 1949 байт формат Gemini CLI .gemini/antigravity-cli/antigravity-oauth-token 505 байт {"auth_method":"consumer","token":{...}} .gemini/antigravity-cli/settings.json 107 байт enableTelemetry, trustedWorkspaces .gemini/antigravity-cli/installation_id 36 байт .gemini/antigravity-cli/jetski_state.pbtxt .gemini/antigravity-cli/history.jsonl .gemini/antigravity-cli/conversation_summaries.db auth.json файл хаба, не agy ``` Вход agy читает из `antigravity-oauth-token`, а не из `oauth_creds.json`. Это установлено сравнением рабочего профиля с неработающим и подтверждено исполнением: файл создали руками для `ag-4` — `agy models` тут же выдал 11 моделей. ### Изоляция по HOME уже работает `get_profile_env_dir`, `build_safe_subprocess_env` и `hidden_process_kwargs` существуют и применяются: `agy models` вызывается с `HOME`/`USERPROFILE`, указывающими на каталог профиля. Заново это писать не надо. ### Заготовка уже есть `launch_native_agy_login` в `agy_subprocess.py` запускает agy с `CREATE_NEW_CONSOLE`. Её никто не вызывает — числится мёртвым кодом с A54. Это отправная точка, а не мусор. ### Рост номеров профилей починен Слот выбирался до входа, когда почта ещё неизвестна, и повторный вход тем же аккаунтом занимал очередной свободный номер: один аккаунт владельца расползся на ag-2, ag-3, ag-4. В `9641957` после опознания почты учётные данные возвращаются в слот, который этот аккаунт уже занимает. **Не переделывать.** ### Среда владельца Сервер: Ubuntu 24.04, рабочий стол на месте (Chrome запускается), владелец сидит за машиной. Вторая машина — Windows 11. Хаб работает на обеих. --- ## P0-1. Вход выполняет сам agy 1. **Запуск `agy` в настоящем терминале** с `HOME` и `USERPROFILE`, указывающими на каталог выбранного профиля. Владелец проходит вход глазами и руками — это единственный доступный способ. 2. **Терминал не подразумевать, а искать.** На Linux проверить наличие эмулятора (`x-terminal-emulator`, `gnome-terminal`, `konsole`, `xfce4-terminal`, `xterm`) и назвать в отказе, что именно искали. Отсутствие терминала — честный отказ с перечнем проверенного, а не молчание. 3. **Файл учётных данных хаб больше не сочиняет.** `write_agy_oauth_creds` и запись `antigravity-oauth-token` остаются только для запасного браузерного пути (P0-4). 4. **Ждать окончания входа по появлению файла**, а не по коду возврата терминала: эмулятор часто отсоединяется сразу. Ждать `antigravity-oauth-token` в каталоге профиля с разумным пределом и внятным сообщением по его истечении. ## P0-2. Слот выбирается до входа и не меняется 1. **Каталог профиля определяется заранее** и передаётся через `HOME`. Вход физически не может уйти в чужой каталог — в этом весь смысл. 2. **Занятый слот не перезаписывать.** Если в каталоге уже лежит рабочий вход другого аккаунта, предупредить и потребовать подтверждения. 3. **Каталоги существующих аккаунтов не трогать.** Их два десятка, повторный вход руками стоит владельцу часов. ## P0-3. Почта берётся из профиля, а не выдумывается 1. **После входа опознать аккаунт**, прочитав то, что записал agy. Если почту установить не удалось — показать `Н/Д` с причиной, а не подставить правдоподобное. 2. **Проверить двойников** уже существующим `AutoAssigner.check_duplicate_identity` и вернуть учётные данные в занятый этим аккаунтом слот, если он есть. 3. **Число и время получения моделей** показывать рядом со списком. ## P0-4. Браузерный путь остаётся запасным 1. **Не удалять существующий OAuth.** С другой машины через браузер это единственный способ, и он работает. 2. **Владелец выбирает способ** в мастере: вход в терминале на этой машине или по ссылке из браузера. Предлагать первым тот, который на текущей машине выполним. 3. **Текст объясняет разницу**: терминал доступен только там, где стоит хаб. ## P0-5. Отказ доходит до владельца 1. **Причина отказа — текстом.** `agy` пишет её в stderr; она обязана попадать в интерфейс вместе с указанием `HOME`, с которым шёл запуск. 2. **Пустых сообщений быть не должно.** Запасной текст «Отказ выполнения действия» означает потерянную причину. 3. **Проверка после входа не блокирует ответ.** Действие возвращается сразу, опрос провайдера идёт в фоне — это сделано в `0ad946e`, не откатывать. ## P0-6. Безопасность 1. **Токены и коды в интерфейс не выводить и в журнал не писать.** В сообщениях допустимы пути и имена файлов, но не содержимое. 2. **Права на каталог и файлы** — `0700` и `0600`. 3. **`~/.hermes/agy_profiles/` не чистить** и не трогать чужие профили. ## P0-7. Проверка исполнением Тестами это не ловится: все прежние дефекты входа прошли через зелёный прогон. 1. **Подключить аккаунт через терминал на сервере** и приложить вывод `agy models` для этого профиля. 2. **Подключить второй аккаунт** и убедиться, что первый не задет: у обоих свои каталоги и свои почты. 3. **Повторить вход тем же аккаунтом** и убедиться, что новый слот не создаётся. 4. **Проверить отказ** при отсутствии терминала: сообщение перечисляет, что искали. 5. **Проверить, что браузерный путь по-прежнему работает** с другой машины. ## P0-8. Аудит вторым проходом 1. **Пройти вход целиком на обеих машинах**, скриншоты приложить. 2. **Убедиться, что хаб не пишет `antigravity-oauth-token`** на пути через CLI: файл создаёт agy. 3. **Проверить, что при отказе входа профиль не остаётся наполовину заполненным** и не числится подключённым. 4. **Различать «нет доступа» и «не найдено»** — не повторять ошибку ложного диагноза. 5. **Побочные изменения** объяснить. 6. **Пропущенный пункт назвать пропущенным.** --- ## Ограничения - Учётные данные и каталоги существующих аккаунтов не трогать. - Правки ревьюера из `main` не откатывать: `9641957` (запись токена и слоты), `0ad946e` (проверка в фоне), `f188a18` (устаревший вердикт). - Фронтенд без npm, без сборки, без фреймворков — по `docs/web-api/CONTRACT.md` §1. - Адреса, пути и имена терминалов в код не зашивать вслепую: искать и сообщать, что искали. - Версию `0.1.3` не понижать. - Правило честности без исключений: неизмеренное — `Н/Д` с причиной; отсутствие прав — не то же самое, что отсутствие файла. ## Критерии приёмки 1. Ветка в `origin`, `git status` чист. 2. Вход через `agy` в терминале работает на Linux и на Windows; вывод `agy models` приложен. 3. Файл `antigravity-oauth-token` на этом пути создаёт agy, а не хаб. 4. Слот задаётся до входа через `HOME`; чужой каталог затронуть невозможно. 5. Повторный вход тем же аккаунтом не создаёт новый слот. 6. Почта берётся из профиля; неустановленная показывается как `Н/Д` с причиной. 7. Браузерный путь сохранён и проверен с другой машины. 8. Отсутствие терминала даёт отказ с перечнем проверенного. 9. Токены не попадают ни в интерфейс, ни в журнал. 10. `ruff check .` чисто; релизный гейт 10/10; тестов не меньше **626**. 11. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. ## Главное Хаб сегодня подделывает чужой формат учётных данных. Это работает ровно до следующего обновления `agy`, и отказ будет молчаливым: файл на месте, вход не засчитан, причина неочевидна. Владелец уже потерял на этом день. `agy` умеет входить сам и делает это правильно по определению. Задание переносит вход туда, где ему место, оставляя браузерный путь для удалённого случая. ## Порядок сдачи Передать точный `FINAL_COMMIT_SHA`.