docs(agents): задание A61 — установщик и релиз на настоящей машине

Для agy: три installer-теста и компиляция C# исключены из каждого прогона
CI (addopts = "not installer") и никогда не выполнялись на реальной сборке;
ни один тег release.yml не дошёл до публикации (все падали на Release Gate,
устранено в HUB-1, но конвейер после починки ни разу не прогонялся). Задание
просит собрать dist/HermesHubSetup.exe, прогнать installer-тесты и один цикл
release.yml на настоящей Windows-машине с реальными учётными данными agy —
это то, что серверная сессия сделать не может.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
ochenstarik-ui 2026-09-03 21:39:56 +07:00
parent 89435eadb5
commit 372be71de7

View file

@ -0,0 +1,207 @@
# Задание A61: установщик и релизный конвейер — проверка на настоящей машине
## Для кого
**agy** (машина владельца, Windows, реальные учётные данные и `agy`). Не для
серверной сессии: у неё нет `csc.exe`, нет Windows-реестра, нет прав публиковать
релиз от имени владельца. Ревьюер (сессия на ПК) принимает.
## Дата поступления
2026-09-03
## База
`origin/main` (`89435ea`).
```
git fetch origin --prune
git checkout -b installer/a61-live-verification origin/main
```
В `main` напрямую не пушить.
---
## Задача
HUB-1 довёл CI до зелёного на Windows и Linux и закрыл дыру в релизных
воротах: `release_gate.py` перестал заявлять проверку хеша, которой не было, и
перестал быть fail-open при обрыве сети или 404. Заодно нашлось — и осталось
непроверенным вживую, потому что для этого нужна настоящая Windows-машина, а
не CI-раннер:
Установщик — единственный способ, которым продукт попадает к владельцу, и он
**не проверяется нигде за пределами CI-раннера**, который сам его никогда не
собирает. Ни один прогон `pytest -m installer` не выполнялся на настоящей
установке. Ни один релиз ещё не прошёл через конвейер целиком — все прошлые
теги падали на `Release Gate Check` (см. `agents/done/2026-09-02-HUB1-audit-p0-green-main.md`,
раздел «Найдено сверх задания»), а действующие релизы на GitHub собраны и
выложены вручную, мимо `release.yml`.
Это задание не про код хаба — про то, что установщик и конвейер публикации
делают на реальной машине то же, что декларируют.
---
## Что уже проверено — заново не выяснять
### CI зелёный, но установщика не касается
`pyproject.toml`:
```
addopts = "-m 'not live and not network and not installer'"
```
Три теста в `tests/test_installer.py`, помеченные `@pytest.mark.installer`
(`test_setup_exe_exists`, `test_silent_installer_execution_with_hermes`,
`test_silent_installer_fails_without_hermes`), **исключены из каждого прогона**
по умолчанию, и ни в `.github/workflows/ci.yml`, ни в `release.yml` нет шага,
который передавал бы `-m installer` явно. К тому же все три сами пропускают
себя (`pytest.skip`), если `dist/HermesHubSetup.exe` не собран — а его никто
не собирает ни в CI, ни в конвейере релиза.
`tests/test_installer_windows_and_linux.py::test_windows_csharp_launchers_and_setup_compile`
пропускается в CI с `csc.exe compiler not found in standard .NET Framework
location` — компилятор ищется по путям `C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe`
и `...\Framework\v4.0.30319\csc.exe`; на `windows-latest` раннере GitHub его
нет. На обычной Windows 10/11 он есть — так и написано в
`installer/README.md`: «compiles `HermesHubSetup.cs` using standard .NET
Framework `csc.exe` present on all Windows 10/11 machines without extra
toolchains».
### Тесты уже изолированы от твоего реестра
`test_silent_installer_execution_with_hermes` и
`test_silent_installer_fails_without_hermes` подставляют `HERMES_HOME`,
`LOCALAPPDATA`, `APPDATA`, `USERPROFILE` во временный каталог и ставят
`HERMES_HUB_NO_REGISTRY=1` — это отключает запись в `HKCU\...\Uninstall`
(закрыто ещё в A4, см. `agents/done/2026-08-21-A4-antigravity-credential-isolation.md`).
Прогон этих тестов не трогает твой реальный реестр и твою реальную установку.
`installer/README.md` отдельно требует того же: «Unit Tests: Must NEVER modify
user Windows Registry or Start Menu shortcuts» — этому требованию тесты уже
следуют, проверить нужно исполнением, а не читать код на слово.
### Релиз ещё никогда не публиковался этим конвейером
`gh run list --workflow=release.yml` на момент HUB-1 показывал failure на всех
пяти последних тегах, включая `v0.1.3-b1` — падение на `Run Release Gate
Check`, той же причине, что красила CI. HUB-1 эту причину устранил, но
**ни разу после починки конвейер не запускался** — значит и новые шаги
(`Built assets must be installable by the updater`,
`Publication Gate (published release must be verifiable)`, оба добавлены в
HUB-1) ни разу не выполнялись на настоящем прогоне GitHub Actions, только
локально функциями напрямую.
---
## P0-1. Собрать установщик и прогнать installer-тесты на настоящей машине
1. Собрать: `installer/build_installer.ps1` (компилирует `HermesHub.cs`,
`HermesHubWeb.cs`, `HermesHubSetup.cs` через `csc.exe`, кладёт
`dist/HermesHubSetup.exe`). Приложить вывод сборки.
2. Прогнать три `installer`-теста явно, отдельно от общего набора:
```
pytest -m installer tests/test_installer.py -v
```
Все три должны выполниться (не `SKIPPED`) и пройти. Приложить полный вывод.
3. Прогнать `test_windows_csharp_launchers_and_setup_compile` отдельно —
на твоей машине `csc.exe` должен найтись. Приложить вывод; если и здесь
`SKIPPED` — назвать точный путь, по которому компилятор искался и не
нашёлся, и где он есть на самом деле.
4. **Подтвердить исполнением, что реестр не тронут**: снять состояние
`HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\HermesHub` до и
после прогона (`reg query`), приложить оба вывода. Совпадают — тесты не
соврали про изоляцию.
## P0-2. Полный цикл `/silent` на реальной установке
1. Установить через `dist/HermesHubSetup.exe /silent` в **реальный**
(не временный) профиль — как ставит владелец.
2. Проверить коды возврата по правилу из `agents/AGENTS.md` §4: `0`, `10`,
`11`, `12` — на тех сценариях, для которых они определены (обычная
установка, установка без Hermes Agent, повторная установка, откат).
Каждый код — с описанием сценария, который его вызвал.
3. После установки — обычный рабочий цикл: хаб запускается, видит существующие
профили `agy`, ничего не потеряно. Если что-то потерялось — это находка, а
не повод откатывать проверку молча.
4. **Не удалять существующие профили и учётные данные для эксперимента.**
Если для чистоты нужна отдельная установка — использовать переменные
изоляции (`HERMES_HOME` и т.д.), как это уже делают тесты, а не боевой
каталог.
## P0-3. Один настоящий прогон релизного конвейера — без публикации владельцу
Цель — увидеть, что новые шаги `release.yml` (Release Gate → сборка →
проверка пригодности ассетов → публикация → Publication Gate) действительно
отрабатывают на GitHub Actions, а не только в теории.
1. **Не создавать публичный релиз без отдельного разрешения владельца.**
Вместо реального тега: либо (а) временный форк/ветка с ручным запуском
`workflow_dispatch`, если конвейер его поддерживает — иначе не добавлять
`workflow_dispatch` ради этого задания, это отдельное решение; либо (б)
прогнать шаги локально в том порядке, в котором их вызывает `release.yml`:
```
python scripts/release_gate.py
# сборка через build_installer.ps1 в dist/
python scripts/release_gate.py --assets dist
```
и явно объяснить, что осталось непроверенным без настоящей публикации
(шаг `Publish GitHub Release` и `--publication-only` после него).
2. Если владелец в диалоге явно разрешит настоящий тестовый тег — тогда можно
довести до конца, включая `release_gate.py --publication-only` на
опубликованном релизе. **Без этого разрешения — не пушить тег.**
3. Итог — что именно проверено, а что нет и почему (например: «сборка и
проверка пригодности ассетов проверены локально в точности как в
`release.yml`; публикация и Publication Gate не проверены — нужен реальный
тег, разрешения не спрашивал/владелец отказал»).
## P0-4. Проверка исполнением, а не по чтению кода
Как и в HUB-1: там, где что-то не запускалось — не писать «должно работать»,
запустить и приложить вывод. Не удалось — сказать `Н/Д` с точной причиной
(например: «на этой машине нет .NET Framework 4.0, только .NET 8» — если это
окажется так).
---
## Ограничения
- **Не публиковать релиз на GitHub без явного разрешения владельца в этом
диалоге.** Прогон `release.yml` через настоящий тег создаёт публичный релиз.
- Реальные учётные данные и `~/.hermes/agy_profiles/` не удалять и не менять
ради эксперимента; для изоляции — переменные окружения, как в существующих
тестах.
- Правки ревьюера из `main` не откатывать; правки HUB-1 (P0-1, P0-2 из этого
задания опираются на них) не переписывать без причины.
- Версию `0.1.3` не понижать и не менять без необходимости.
- Правило честности без исключений: неизмеренное — `Н/Д` с причиной.
- Если для `workflow_dispatch` нужно менять `.github/workflows/release.yml`
делать это отдельным, явно описанным шагом, не молча.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. `dist/HermesHubSetup.exe` собран на настоящей Windows-машине; вывод сборки
приложен.
3. Все installer-тесты (`pytest -m installer` + компиляция C#) выполнены не
как `SKIPPED`; вывод каждого приложен.
4. `HKCU\...\Uninstall\HermesHub` до и после прогона тестов идентичен —
оба снятых состояния приложены.
5. `/silent` установка проверена на реальном профиле; коды возврата названы
со сценарием каждого.
6. Локальный прогон шагов `release.yml` (Release Gate → сборка → проверка
ассетов) воспроизведён и приложен; либо — с явного разрешения владельца —
доведён до настоящего тега и `--publication-only`.
7. Каждый непроверенный пункт назван явно, с причиной — не пропущен молча.
8. Отчёт: что собрано, что запущено, точные команды и их вывод, что осталось
`Н/Д` и почему.
## Главное
HUB-1 сделал ворота честными на уровне кода: они больше не заявляют проверку,
которой не было. Это задание проверяет ту же честность на уровне машины —
что установщик, который получит владелец, действительно собирается, ставится
и обновляется так, как об этом говорит код. Пока это не проверено на
настоящей Windows, «зелёный CI» доказывает только код, а не установщик.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA` и полный вывод всех проверок из P0-1—P0-3.