hermes-hub/agents/inbox/2026-09-02-A59-visible-update.md
Hermes Team 4fa993938b docs(agents): задание A59 — обновление, которое видно и доводит себя до конца
Владелец показал, как это сделано в Cockpit Tools: окно при запуске, видимая
загрузка, останов служб, установка и запуск без участия человека.

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

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

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 11:12:26 +07:00

151 lines
12 KiB
Markdown
Raw Permalink 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.

# Задание 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`.