# Задание A58: хаб видит состояние проверки доступности agy ## Дата поступления 2026-09-02 ## База `origin/main` (`e431e39`). ``` git fetch origin --prune git checkout -b antigravity/a58-agy-eligibility-state origin/main ``` В `main` напрямую не пушить. ## Порядок исполнения Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-7** написан для аудитора. Зона: обнаружение состояния `agy`. С кодом входа (A57) пересекается только чтением пути к исполняемому файлу. --- ## Задача Владелец не может пользоваться Antigravity: `agy` отвечает ``` Eligibility check failed: Your current account is not eligible for Antigravity, because it is not currently available in your location. ``` Вход при этом проходит полностью: терминал открывается, каталог профиля верный, аккаунт опознан. Отказывает Google. Владелец обходит это сторонним патчером, который держит у себя. После каждого обновления `agy` патч слетает, и владелец узнаёт об этом, только наткнувшись на отказ посреди работы. Задание закрывает именно это: **хаб должен замечать смену состояния и говорить о ней**, а не оставлять владельца выяснять причину заново. --- ## Что проверено ревьюером — заново не выяснять ### Проверка не в клиенте, но отказ выносит клиент В бинарнике `agy` **нет** строки «not currently available in your location» — её присылает сервер. При этом есть перечисление `EPD_ELIGIBILITY_NOT_ELIGIBLE_REGION_OUT_OF_SCOPE`, `ENDPOINT_AIM_ELIGIBILITY` и `AIM_ELIGIBILITY_FETCH_STATUS_*`: клиент запрашивает право доступа у Google и отказывается работать сам. ### Прокси не помогает — ограничение привязано к аккаунту Измерено на сервере владельца: выход через Финляндию и через Данию даёт один и тот же отказ. Описание патчера это подтверждает — он снимает ограничение «без VPN и смены региона аккаунта Google», то есть обычные пути именно эти два. **Поддержку прокси, добавленную в `fa7bbef`, не удалять**: она нужна и работает, просто эту задачу не решает. ### Что делает патчер Для CLI это правка машинного кода, а не настройка. Ищется последовательность байтов и переписывается так, чтобы ветвление всегда уходило по разрешённому пути: ``` было: test rax,rax ; je eligible ; cmp byte[rax+8],0 ; jne eligible ; call failure стало: test rax,rax ; je eligible ; test rax,rax ; nop ; jne eligible ``` Четыре байта. В исходнике патчера это названо «единственный гейт начальной проверки». Есть подписи для x86-64 и для arm64. Подменять в настройках нечего: проверка не в настройках. ### Версии У владельца `Antigravity CLI 1.1.23`. Патчер объявляет минимальные версии `2.5.5` и `2.9.1` — соответствие надо проверить, иначе подпись не найдётся. Обновление CLI выполняется командой `agy update` и перезаписывает файл, снимая патч. --- ## P0-1. Хаб не патчит ничего сам 1. **Хаб не изменяет исполняемые файлы.** Ни при каких условиях, ни по кнопке, ни автоматически. 2. **Хаб ничего не скачивает и не запускает из сети.** Стороннего кода в хабе нет. 3. **Только чтение**: состояние определяется чтением файла, который уже лежит на машине. ## P0-2. Состояние определяется и показывается 1. **Признак патча** — по наличию в файле изменённой последовательности байтов. Подписи для x86-64 и arm64. Чтение файла, ничего больше. 2. **Три состояния, а не два**: «проверка снята», «проверка на месте», «определить не удалось» — с причиной. Не найдена подпись ни в исходном, ни в изменённом виде означает именно третье: другая версия CLI, а не «не пропатчен». 3. **Версия и отпечаток файла** запоминаются. Смена любого из них после обновления — повод пересчитать состояние и сказать владельцу. 4. **Показывать в карточке аккаунта Antigravity** и в «Состоянии системы». ## P0-3. Владелец узнаёт о смене состояния 1. **Событие в журнале**, когда состояние сменилось: было «снята» — стало «на месте». 2. **Заметное указание в интерфейсе**, а не строчка в глубине: этот отказ останавливает работу целиком. 3. **Не опрашивать в цикле.** Достаточно проверки при запуске, после обновления `agy` и по кнопке. Опрос в цикле уже приводил к тому, что интерфейс сам себя кормил запросами. ## P0-4. Кнопка запускает то, что владелец сам поставил 1. **Путь к сценарию владельца задаётся в настройках.** Умолчания не выдумывать: не задан — кнопки нет, показывается `Н/Д: сценарий не указан`. 2. **Запуск только по нажатию.** Никакого автоматического запуска при обновлении: владелец должен видеть, что и когда выполняется. 3. **Запуск в терминале**, как вход в A57 — владелец видит ход и результат. Использовать существующий `find_terminal_emulator`, заново не писать. 4. **После выполнения состояние пересчитывается** и показывается новое. 5. **Отказ запуска доходит текстом**, с указанием пути и причины. ## P0-5. Обновление CLI 1. **Показывать установленную версию** `agy`. Не удалось определить — `Н/Д` с причиной. 2. **Кнопка обновления** выполняет `agy update` в терминале. 3. **Предупредить о порядке**: обновление перезаписывает файл и снимает патч, поэтому сначала обновление, потом патч. Это подсказка в интерфейсе, а не комментарий в коде. ## P0-6. Проверка исполнением 1. **Определить состояние на настоящем `agy` владельца** и приложить вывод. 2. **Проверить все три состояния**, третье — на файле другой версии. 3. **Проверить, что хаб файл не изменил**: контрольная сумма до и после определения состояния совпадает. 4. **Проверить кнопку** на незаданном пути и на неверном. ## P0-7. Аудит вторым проходом 1. **Убедиться, что хаб не пишет в исполняемый файл** ни на одном пути. 2. **Проверить, что «определить не удалось» не выдаётся за «не пропатчен»** — это разные вещи, и путать их нельзя. 3. **Проверить, что нет опроса в цикле.** 4. **Побочные изменения** объяснить. 5. **Пропущенный пункт назвать пропущенным.** --- ## Ограничения - Хаб не изменяет чужие исполняемые файлы и не выполняет загруженный из сети код. - Поддержку прокси из `fa7bbef` не удалять. - Правки ревьюера из `main` не откатывать. - Фронтенд без npm, без сборки, без фреймворков — по `docs/web-api/CONTRACT.md` §1. - Пути и версии в код не зашивать: определять и сообщать, что проверяли. - Версию `0.1.3` не понижать. - Правило честности без исключений: неопределённое — `Н/Д` с причиной. ## Критерии приёмки 1. Ветка в `origin`, `git status` чист. 2. Состояние проверки определяется на настоящем `agy`; вывод приложен. 3. Три состояния различаются; «определить не удалось» называет причину. 4. Контрольная сумма исполняемого файла до и после определения совпадает. 5. Смена состояния после обновления `agy` попадает в журнал и видна в интерфейсе. 6. Кнопка запускает указанный владельцем сценарий в терминале; путь не задан — кнопки нет. 7. Показывается версия `agy`; есть кнопка `agy update` с предупреждением о порядке. 8. Опроса в цикле нет. 9. `ruff check .` чисто; релизный гейт 10/10; тестов не меньше **704**. 10. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. ## Главное Владелец теряет время не на сам обход, а на то, что узнаёт о слетевшем патче случайно — посреди работы, по невнятному отказу. Хаб для того и нужен, чтобы состояние было видно заранее. Поэтому хаб **смотрит и говорит**, а действие остаётся за владельцем и выполняется его собственным средством. Патчить чужой бинарник самому хабу нельзя: подпись привязана к версии, любое обновление её ломает, и отлаживать пришлось бы чужой код внутри своего. ## Порядок сдачи Передать точный `FINAL_COMMIT_SHA`.