Fix Monitor snapshot contract and alpha.9 release compatibility #32

Merged
ochenstarik-ui merged 1 commit from hermes/monitor-snapshot-contract into main 2026-08-10 10:31:10 +00:00
ochenstarik-ui commented 2026-08-10 10:24:26 +00:00 (Migrated from github.com)

Hermes: формат снимка Monitor, совместимость БД, дисциплина релизов

Состояние

  • main @ f9205c3, роль Monitor слита (#29), подписанная поставка Queue A слита (#26);
  • v0.1.0-alpha.8 пересобран, все Linux-артефакты и server-monitor-manager-manifest.sig на месте;
  • открыт PR #31 с починкой путей Windows-артефактов.

Ветка: hermes/monitor-snapshot-contract.


Часть 1 — снимок Monitor не читается Desktop · блокирующий

Роль Monitor установлена, но мониторинг работать не будет. Скрипт /usr/local/libexec/ochenstarik-smm-metrics выдаёт имена полей, которых не понимает ни парсер Desktop, ни собственный контракт проекта.

Ждёт SshMonitorService.QueryAsync:

PROTOCOL HOSTNAME UPTIME_SECONDS LOAD1 CPU_COUNT
MEM_TOTAL_KB MEM_AVAILABLE_KB SWAP_TOTAL_KB SWAP_FREE_KB
DISK_TOTAL_KB DISK_AVAILABLE_KB DISK_INODES_TOTAL DISK_INODES_FREE
NETWORK_RX_BYTES NETWORK_TX_BYTES SYSTEMD_SSH SYSTEMD_WIREGUARD

Выдаёт скрипт:

CPU_COUNT LOAD1 MEM_TOTAL MEM_AVAIL SWAP_TOTAL SWAP_FREE
DISK_TOTAL DISK_AVAIL INODES_TOTAL INODES_FREE
NET_RX NET_TX UPTIME KERNEL DF_OUT DF_INODES MESH_STATUS

Совпадают два поля из шестнадцатиCPU_COUNT и LOAD1. Остальные не совпадают по имени, а PROTOCOL, HOSTNAME, SYSTEMD_SSH, SYSTEMD_WIREGUARD отсутствуют вовсе.

Практический результат: в Desktop имя сервера подставится из профиля, память, диск, swap, inode и сеть покажут нули, состояния SSH и WireGuard — unknown. Формально роль установлена, фактически функция, ради которой существует Desktop, не работает.

Формат уже зафиксирован в docs/installer-contract.md §7 — его и надо соблюсти дословно, а не изобретать заново.

Что сделать

  1. Привести вывод скрипта к docs/installer-contract.md §7: PROTOCOL=1, HOSTNAME, UPTIME_SECONDS, LOAD1, CPU_COUNT, MEM_TOTAL_KB, MEM_AVAILABLE_KB, SWAP_TOTAL_KB, SWAP_FREE_KB, DISK_TOTAL_KB, DISK_AVAILABLE_KB, DISK_INODES_TOTAL, DISK_INODES_FREE, NETWORK_RX_BYTES, NETWORK_TX_BYTES, KERNEL.
  2. Добавить SYSTEMD_SSH и SYSTEMD_WIREGUARD — их читает Desktop, но в §7 их нет. Дописать в §7, чтобы контракт снова был единственным источником.
  3. Внутренние переменные вроде DF_OUT и DF_INODES из вывода убрать: снимок не должен содержать ничего, кроме полей контракта.

Контрактный тест — переделать

tests/acceptance/test_monitor_snapshot.sh проверяет скрипт против списка полей, который живёт в самом тесте. Именно поэтому расхождение с Desktop не поймалось.

Список ожидаемых полей должен существовать в одном месте и использоваться обеими сторонами:

  • тестом shell-скрипта — что все поля присутствуют и лишних нет;
  • тестом парсера Desktop — что он читает ровно эти поля.

Как реализовать — на ваше усмотрение: общий файл-фикстура с эталонным снимком, из которого обе стороны берут набор ключей, либо генерация списка из installer-contract.md. Требование одно: изменение имени поля с одной стороны обязано ронять тест другой стороны.

SshMonitorService.cs при этом не менять — правится скрипт, а не парсер. Если парсер тоже потребует правки, описать в REPORT.md.


Часть 2 — совместимость существующей БД с SQLitePCLRaw 3.0.5

Пункт из прошлого задания, оставшийся невыполненным. Сейчас он не горит только по счастливой случайности: alpha.8 собран из коммита, где ещё 2.1.12. Но в main уже 3.0.5, и следующий релиз его унесёт.

На живом Hub пользователя база создана версией 2.1.12. Если совместимости нет, это проявится в момент update-control.

Проверить: открытие существующей control.db сборкой из текущего main, PRAGMA user_version без повторного применения миграций, чтение агентов, identities, links, provisioning и аудита, backup-create и backup-restore на этой же базе, и то же самое на linux-arm64 self-contained trimmed single-file.

Добавить постоянный тест на открытие базы предыдущей схемы — эталонная control.db в репозитории либо скрипт её воспроизведения. Без него следующее обновление SQLite повторит эту историю.

Если хоть одна проверка не проходит — откатить #23 отдельным PR и написать об этом прямо.


Часть 3 — дисциплина релизов

Тег v0.1.0-alpha.8 был сдвинут: сначала указывал на 80b4797, теперь на ad180e9. Так делать нельзя, и теперь особенно: релиз содержит server-monitor-manager-manifest.json и подпись manifest.sig, которые описывают конкретное содержимое. Если тег двигается, подпись перестаёт что-либо доказывать, а у того, кто сверялся с прежним тегом, проверка не сойдётся.

  1. Зафиксировать правило в docs/installer-contract.md: опубликованный тег неизменяем; ошибка в сборке исправляется выпуском следующей версии, а не переписыванием тега.
  2. Следующий релиз выпускать как v0.1.0-alpha.9 после частей 1 и 2.
  3. Убрать из smm-setup.sh (ассет релиза) временный обход бага validate_control_url — дефект исправлен в #24, обход помечен комментарием в коде.
  4. Довести или закрыть PR #31.

Критерий приёмки

  • снимок Monitor совпадает с installer-contract.md §7 плюс два поля systemd; лишних полей нет;
  • переименование любого поля роняет тест противоположной стороны — продемонстрировать намеренной поломкой во временном коммите со ссылкой на красный прогон;
  • существующая база открывается новой сборкой, есть постоянный тест на предыдущую схему;
  • правило неизменяемости тега записано в контракте;
  • обход validate_control_url из smm-setup.sh удалён;
  • Control suite прогнан на Linux, CI зелёный.

Отчёт

Раздельно: локально, в CI со ссылками, не запускалось и почему.

# Hermes: формат снимка Monitor, совместимость БД, дисциплина релизов ## Состояние - `main` @ `f9205c3`, роль Monitor слита (#29), подписанная поставка Queue A слита (#26); - `v0.1.0-alpha.8` пересобран, все Linux-артефакты и `server-monitor-manager-manifest.sig` на месте; - открыт PR #31 с починкой путей Windows-артефактов. Ветка: `hermes/monitor-snapshot-contract`. --- ## Часть 1 — снимок Monitor не читается Desktop · блокирующий Роль Monitor установлена, но мониторинг работать не будет. Скрипт `/usr/local/libexec/ochenstarik-smm-metrics` выдаёт имена полей, которых не понимает ни парсер Desktop, ни собственный контракт проекта. **Ждёт `SshMonitorService.QueryAsync`:** ``` PROTOCOL HOSTNAME UPTIME_SECONDS LOAD1 CPU_COUNT MEM_TOTAL_KB MEM_AVAILABLE_KB SWAP_TOTAL_KB SWAP_FREE_KB DISK_TOTAL_KB DISK_AVAILABLE_KB DISK_INODES_TOTAL DISK_INODES_FREE NETWORK_RX_BYTES NETWORK_TX_BYTES SYSTEMD_SSH SYSTEMD_WIREGUARD ``` **Выдаёт скрипт:** ``` CPU_COUNT LOAD1 MEM_TOTAL MEM_AVAIL SWAP_TOTAL SWAP_FREE DISK_TOTAL DISK_AVAIL INODES_TOTAL INODES_FREE NET_RX NET_TX UPTIME KERNEL DF_OUT DF_INODES MESH_STATUS ``` Совпадают **два поля из шестнадцати** — `CPU_COUNT` и `LOAD1`. Остальные не совпадают по имени, а `PROTOCOL`, `HOSTNAME`, `SYSTEMD_SSH`, `SYSTEMD_WIREGUARD` отсутствуют вовсе. Практический результат: в Desktop имя сервера подставится из профиля, память, диск, swap, inode и сеть покажут нули, состояния SSH и WireGuard — `unknown`. Формально роль установлена, фактически функция, ради которой существует Desktop, не работает. Формат уже зафиксирован в `docs/installer-contract.md` §7 — его и надо соблюсти дословно, а не изобретать заново. ### Что сделать 1. Привести вывод скрипта к `docs/installer-contract.md` §7: `PROTOCOL=1`, `HOSTNAME`, `UPTIME_SECONDS`, `LOAD1`, `CPU_COUNT`, `MEM_TOTAL_KB`, `MEM_AVAILABLE_KB`, `SWAP_TOTAL_KB`, `SWAP_FREE_KB`, `DISK_TOTAL_KB`, `DISK_AVAILABLE_KB`, `DISK_INODES_TOTAL`, `DISK_INODES_FREE`, `NETWORK_RX_BYTES`, `NETWORK_TX_BYTES`, `KERNEL`. 2. Добавить `SYSTEMD_SSH` и `SYSTEMD_WIREGUARD` — их читает Desktop, но в §7 их нет. Дописать в §7, чтобы контракт снова был единственным источником. 3. Внутренние переменные вроде `DF_OUT` и `DF_INODES` из вывода убрать: снимок не должен содержать ничего, кроме полей контракта. ### Контрактный тест — переделать `tests/acceptance/test_monitor_snapshot.sh` проверяет скрипт против списка полей, который живёт в самом тесте. Именно поэтому расхождение с Desktop не поймалось. Список ожидаемых полей должен существовать **в одном месте** и использоваться обеими сторонами: - тестом shell-скрипта — что все поля присутствуют и лишних нет; - тестом парсера Desktop — что он читает ровно эти поля. Как реализовать — на ваше усмотрение: общий файл-фикстура с эталонным снимком, из которого обе стороны берут набор ключей, либо генерация списка из `installer-contract.md`. Требование одно: **изменение имени поля с одной стороны обязано ронять тест другой стороны.** `SshMonitorService.cs` при этом не менять — правится скрипт, а не парсер. Если парсер тоже потребует правки, описать в `REPORT.md`. --- ## Часть 2 — совместимость существующей БД с SQLitePCLRaw 3.0.5 Пункт из прошлого задания, оставшийся невыполненным. Сейчас он не горит только по счастливой случайности: `alpha.8` собран из коммита, где ещё `2.1.12`. Но в `main` уже `3.0.5`, и следующий релиз его унесёт. На живом Hub пользователя база создана версией `2.1.12`. Если совместимости нет, это проявится в момент `update-control`. Проверить: открытие существующей `control.db` сборкой из текущего `main`, `PRAGMA user_version` без повторного применения миграций, чтение агентов, identities, links, provisioning и аудита, `backup-create` и `backup-restore` на этой же базе, и то же самое на `linux-arm64` self-contained trimmed single-file. **Добавить постоянный тест** на открытие базы предыдущей схемы — эталонная `control.db` в репозитории либо скрипт её воспроизведения. Без него следующее обновление SQLite повторит эту историю. Если хоть одна проверка не проходит — откатить `#23` отдельным PR и написать об этом прямо. --- ## Часть 3 — дисциплина релизов Тег `v0.1.0-alpha.8` был сдвинут: сначала указывал на `80b4797`, теперь на `ad180e9`. Так делать нельзя, и теперь особенно: релиз содержит `server-monitor-manager-manifest.json` и подпись `manifest.sig`, которые описывают конкретное содержимое. Если тег двигается, подпись перестаёт что-либо доказывать, а у того, кто сверялся с прежним тегом, проверка не сойдётся. 1. Зафиксировать правило в `docs/installer-contract.md`: **опубликованный тег неизменяем**; ошибка в сборке исправляется выпуском следующей версии, а не переписыванием тега. 2. Следующий релиз выпускать как `v0.1.0-alpha.9` после частей 1 и 2. 3. Убрать из `smm-setup.sh` (ассет релиза) временный обход бага `validate_control_url` — дефект исправлен в #24, обход помечен комментарием в коде. 4. Довести или закрыть PR #31. --- ## Критерий приёмки - снимок Monitor совпадает с `installer-contract.md` §7 плюс два поля systemd; лишних полей нет; - переименование любого поля роняет тест противоположной стороны — продемонстрировать намеренной поломкой во временном коммите со ссылкой на красный прогон; - существующая база открывается новой сборкой, есть постоянный тест на предыдущую схему; - правило неизменяемости тега записано в контракте; - обход `validate_control_url` из `smm-setup.sh` удалён; - Control suite прогнан на Linux, CI зелёный. ## Отчёт Раздельно: локально, в CI со ссылками, не запускалось и почему.
ochenstarik-ui commented 2026-08-10 10:31:07 +00:00 (Migrated from github.com)

Verification evidence:

Intentional cross-contract red proof:

  • temporary commit 28916b01fa3dd1859f3879c43f2b33639a6c7c0a renamed Desktop MEM_TOTAL_KB to MEM_TOTAL; the opposite-side canonical contract failed exactly as required: https://github.com/ochenstarik-ui/server-monitor-manager/actions/runs/31379098394
  • failure: expected MEM_TOTAL_KB, actual MEM_TOTAL; 119 passed / 1 failed.
  • the proof commit is isolated on hermes/monitor-contract-red-proof and is not part of this PR.
Verification evidence: - Independent worker-review verdict: **PASS** (full original task + complete diff bundle reviewed). - Local Control suite: **120/120 passed**; focused Monitor/DB/release contracts passed; format and `git diff --check` passed. - Linux control and agent: https://github.com/ochenstarik-ui/server-monitor-manager/actions/runs/31378990081 - Linux platform matrix (including native arm64 VMs): https://github.com/ochenstarik-ui/server-monitor-manager/actions/runs/31378989933 - Windows build: https://github.com/ochenstarik-ui/server-monitor-manager/actions/runs/31378989978 Intentional cross-contract red proof: - temporary commit `28916b01fa3dd1859f3879c43f2b33639a6c7c0a` renamed Desktop `MEM_TOTAL_KB` to `MEM_TOTAL`; the opposite-side canonical contract failed exactly as required: https://github.com/ochenstarik-ui/server-monitor-manager/actions/runs/31379098394 - failure: expected `MEM_TOTAL_KB`, actual `MEM_TOTAL`; 119 passed / 1 failed. - the proof commit is isolated on `hermes/monitor-contract-red-proof` and is not part of this PR.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: ochenstarik/server-monitor-manager#32
No description provided.