docs(agents): задание A59 — обновление, которое видно и доводит себя до конца

Владелец показал, как это сделано в Cockpit Tools: окно при запуске, видимая
загрузка, останов служб, установка и запуск без участия человека.

Строить заново нечего. Проверено: проверка при запуске уже выполняется, но в
тихом режиме; обработчик хода скачивания в загрузчике уже написан, но его
результат никуда не выводится; останов и перезапуск держатся на schedule_restart
и не проверены на обеих системах.

Внешнее условие: лента релизов отстала на v0.1.2-b7 при установленной 0.1.3 —
пока свежий релиз не опубликован, обновлять не на что.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hermes Team 2026-09-02 11:12:26 +07:00
parent 58cb88e529
commit 4fa993938b

View file

@ -0,0 +1,151 @@
# Задание A59: обновление, которое видно и доводит себя до конца
## Дата поступления
2026-09-02
## База
`origin/main` (`58cb88e`).
```
git fetch origin --prune
git checkout -b antigravity/a59-visible-update origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-7** написан для аудитора.
Зона: обновление и перезапуск. С A58 (состояние `agy`) не пересекается.
---
## Задача
Владелец показал, как это устроено в Cockpit Tools, и хочет так же:
> захожу в программу и независимо от того, работала она или нет, выходит окно об
> обновлении. ставишь новую версию (что на линукс, что на винде) — сразу видно
> загрузку и что скачивается. потом он останавливает сам все службы,
> устанавливает программу новую и запускает.
Сейчас владелец ставит каждую сборку установщиком вручную. Обновление внутри программы написано, но не доведено до вида, в котором им пользуются.
---
## Что проверено ревьюером — заново не выяснять
Строить с нуля ничего не надо, почти всё уже есть.
```
UpdateManager.check_for_updates есть
UpdateManager._download_file есть, с обработчиком хода: content-length и
progress_cb(downloaded / total)
UpdateManager.download_and_verify есть, с проверкой SHA-256
UpdateManager.install_latest_update есть
UpdateManager.schedule_restart есть
действия check_updates и apply_update есть в обработчике
проверка при запуске сервера есть: server.py вызывает check_for_updates
проверка при открытии интерфейса есть: app.js вызывает checkUpdates(true)
```
Три разрыва, и все на виду.
1. **Проверка при запуске молчит.** `checkUpdates(true)` — тихий режим: обновление находится, но владельцу не показывается ничего.
2. **Ход скачивания никуда не идёт.** `progress_cb` в загрузчике есть, но его никто не передаёт и результат не отображается.
3. **Останов служб и запуск после установки** держится на `schedule_restart` и не проверен на обеих системах.
Плюс внешнее условие: **лента релизов отстала**. Последний опубликованный — `v0.1.2-b7`, а установлена `0.1.3`. Пока свежий релиз не опубликован, обновлять не на что, и проверить работу нельзя.
---
## P0-1. Окно при запуске
1. **Обновление есть — показывается окно**, а не значок в углу. Независимо от того, работала программа до этого или нет.
2. **В окне: номер версии, что нового, размер загрузки.** «Что нового» брать из описания релиза; нет описания — писать `Н/Д: описание не приложено`, а не пустоту.
3. **Отказаться можно**, и отказ запоминается для этой версии: повторно то же окно не всплывает.
4. **Обновления нет — окна нет.** Молчание при отсутствии новостей.
## P0-2. Скачивание видно
1. **Полоса хода и проценты**, источник — `progress_cb`, он уже написан.
2. **Показывать, что именно скачивается**: имя файла и размер, «сколько из скольких».
3. **Нет `content-length` — так и писать**: `Н/Д: сервер не сообщил размер`, и показывать скачанный объём без процентов. Выдумывать проценты нельзя.
4. **Скачивание можно отменить**, недокачанный файл удаляется.
5. **Проверка SHA-256 остаётся обязательной.** Не сошлась — установка не начинается, файл удаляется, причина на экран.
## P0-3. Установка доводит себя до конца
1. **Останавливаются все свои процессы**: веб-сервер, фоновые опросы, дочерние. Тот же порядок, что в установщике — там это уже сделано в `stop_running_hub`.
2. **Чужого не трогать.** Останавливать только своё: по признаку хаба, в своём пользователе.
3. **Установка и запуск** без участия владельца. После запуска — тот же экран, на котором он был.
4. **Работает на Linux и на Windows.** Разница только в способе запуска, поведение одинаковое.
5. **Сорвалось на середине — откат к прежней версии** и внятное сообщение. Программа обязана остаться работоспособной.
## P0-4. Видно, что обновилось
1. **После перезапуска показать, что версия сменилась**: было — стало.
2. **Строка сборки уже показывает коммит работающего процесса** (`running_commit`, снят при старте) и время запуска. Не ломать: это единственный признак, по которому отличают новый код от старого, пережившего установку.
3. **Событие в журнале** о применённом обновлении с обеими версиями.
## P0-5. Ничего лишнего
1. **Не опрашивать в цикле.** Проверка при запуске и по кнопке. Опрос в цикле уже приводил к тому, что интерфейс сам себя кормил запросами.
2. **Опросы состояния молчат** — они в `SILENT_ACTIONS`, туда же добавить опрос хода загрузки.
3. **Автоматическая установка без спроса запрещена.** Показать, предложить, дождаться нажатия.
## P0-6. Проверка исполнением
Тестами это не ловится: дело в живом переходе между версиями.
1. **Обновиться на живой установке** с предыдущей версии на текущую. На обеих системах. Скриншоты окна и полосы хода приложить.
2. **Замерить время** от нажатия до готовности.
3. **Проверить, что после перезапуска работает новый код** — по `running_commit`, а не по номеру версии.
4. **Проверить отказ**: испорченная сумма, обрыв сети, отмена на середине.
5. **Проверить, что старый процесс не остался.**
## P0-7. Аудит вторым проходом
1. **Пройти обновление целиком на обеих системах.**
2. **Проверить, что проценты не выдумываются** при отсутствии `content-length`.
3. **Проверить откат** при сорвавшейся установке.
4. **Проверить, что останавливается только своё.**
5. **Побочные изменения** объяснить.
6. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Проверку SHA-256 и список разрешённых адресов не ослаблять.
- Показ работающего коммита и времени запуска не ломать.
- Фронтенд без npm, без сборки, без фреймворков — по `docs/web-api/CONTRACT.md` §1.
- Правки ревьюера из `main` не откатывать.
- Версию `0.1.3` не понижать.
- Правило честности без исключений: неизвестный размер — `Н/Д` с причиной, а не поддельные проценты.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. При запуске с доступным обновлением показывается окно; без обновления — не показывается.
3. Отказ от версии запоминается, окно не всплывает повторно.
4. Полоса хода и объём отображаются; без `content-length` — честное `Н/Д` без процентов.
5. Отмена удаляет недокачанный файл.
6. Несовпадение SHA-256 прекращает установку с сообщением.
7. Установка сама останавливает свои процессы, ставит и запускает; проверено на Linux и Windows.
8. Сорвавшаяся установка откатывается, программа остаётся работоспособной.
9. После перезапуска `running_commit` соответствует новой сборке.
10. Опроса в цикле нет; опрос хода загрузки молчалив.
11. `ruff check .` чисто; релизный гейт 10/10; тестов не меньше **708**.
12. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`.
## Главное
Механизм написан, но им нельзя пользоваться: проверка находит обновление и молчит, ход загрузки считается и никуда не выводится. Владелец из-за этого ставит каждую сборку руками, а сегодня их было десять.
Задание не про новый код, а про то, чтобы уже написанное дошло до экрана и довело себя до конца: показать, скачать на глазах, остановить своё, поставить, запустить.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.