server-monitor-manager/agents/_salvage-2026-08-18/smm-deliverables/Старые задачи/smm-gemini-plan-2026-08-04.md
Ochenstarik 23eb3f5233 chore(agents): разбор рабочих папок с диска на 2026-08-18
Задания, отчёты и патчи, лежавшие в C:\Users\Ochenstarik\projects и в
домашней папке, перенесены в agents/. Разложено по агентам там, где имя
файла позволяло определить автора; остальное — в _salvage-2026-08-18/
и разбирается вручную.

Патчи в notes/salvage-2026-08-18/ — незакоммиченная работа из брошенных
рабочих копий: она существовала только на диске.

Тяжёлое (релизные архивы, инсталляторы, наборы данных) в репозиторий не
попало: оно лежит рядом, в Agent_projects/_archive и Agent_projects/_data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 14:19:54 +07:00

20 KiB
Raw Permalink Blame History

План доделывания Server Monitor Manager — для облачного исполнителя (Gemini)

Составлен 2026-08-04. Заменяет собой полосовое разделение: Codex приостановлен, Gemini ведёт весь объём.

Базовая ревизия на GitHub: main @ b11c277.


0. Передача работ — сделать до постановки первой задачи

0.1. B-3R существует только локально

Незавершённая работа по блоку B-3R — 24 изменённых файла, около 1276 добавленных строк — лежит незакоммиченной в C:\Users\Ochenstarik\projects\server-monitor-manager-task3-b3. На GitHub этой ветки нет: последняя ветка серии на remote — hermes/task2-b-link-reconciliation (1580ec7), это ещё блок B-2.

Облачный исполнитель этого не видит. Возможные решения:

Вариант Последствия
Закоммитить и запушить ветку hermes/task3-b3-fact-reconciliation как есть, с честной пометкой «незавершено, см. B3R_SPEC» Работа сохранена, Gemini продолжает с неё. Рекомендуемый вариант
Выгрузить патчем и передать файлом Работает, но патч быстро протухнет и его придётся накатывать вручную
Отбросить и переделать с b11c277 Потеря корректной работы: R3 закрыт полностью, R1 закрыт на уровне отдельной мутации — я это проверял по коду

Пока решение не принято, ставить задачу по B-3R облачному исполнителю нельзя: он либо не найдёт контекст, либо начнёт вторую параллельную реализацию.

0.2. Нормативные документы тоже локальны

Коммит 4de849e (docs/product-horizons.md, docs/approval-policies.md, docs/integration-kagent.md, правки roadmap.md и security-model.md) находится на локальной ветке docs/product-horizons-and-integration и не запушен. Пока он не в репозитории, план ниже ссылается на документы, которых исполнитель не увидит.

Запушить до выдачи первой задачи.


1. Что облачный исполнитель проверить не может

Это самый важный раздел. Дисциплина честной отчётности была сильной стороной предыдущих пакетов — её надо сохранить, а список ограничений изменился.

Проверка Доступно в облаке Что делать
Control test suite на Linux Да Запускать обязательно. Именно Linux-прогон в блоке B-3 выявил, что integration-тест остался на старом протоколе: на Windows он молча пропускался по OperatingSystem.IsLinux()
Тесты helper, nftables, bash-контракты Да Запускать; это естественная среда для них
Сборка Desktop (WinUI 3) Нет Требует Windows и Windows App SDK. Полагаться на windows-build.yml в CI. Никогда не заявлять локальную сборку Desktop
Test-DesktopContracts.ps1 Частично Это сопоставление строк в XAML, идёт под pwsh на Linux. Указывать, что запущено под pwsh, а не на Windows
Физический acceptance Нет ни у кого Требует HUB_SSH_HOST, HUB_SSH_USER, SOURCE_SSH_HOST, SOURCE_SSH_USER, HOME_WG_IP, SECOND_WG_IP, SSH_IDENTITY_FILE. Не выдавать mock- и contract-тесты за него
Trimmed linux-x64 publish Да Полезно: проверка source-generated сериализации на реальном опубликованном артефакте

Правило. В TEST_EVIDENCE.md раздельно перечисляются: что запущено локально, что запущено в CI, что не запускалось и почему. Отсутствие проверки — не дефект отчёта; выдача непроверенного за проверенное — дефект.


2. Формат сдачи для облака

Прежние пакеты складывались в локальную папку. Для облачного исполнителя:

  • Основной артефакт — Pull Request. Якорь целостности — SHA коммита, а не SHA256SUMS. В отчёте указывать точный SHA, который ревьюился, и SHA, который смержен, если они различаются.
  • REPORT.md и TEST_EVIDENCE.md — в описании PR либо отдельным коммитом в PR; содержание прежнее.
  • CI_CHECKS.txt заменяется ссылкой на прогон checks в PR.
  • INDEPENDENT_REVIEW.md — обязателен по-прежнему, и ревьюеру передаётся полный текст задачи, а не только диф. Три блока из четырёх дали находки класса «пропущенное требование», которые при diff-only ревью не ищутся вовсе.
  • Один PR — одна тема. Смешанные PR не принимаются.
  • Статус после merge — merged / verified, а не «выполнено», если критерий сформулирован через фактическое поведение и не измерялся на реальной топологии.

3. Первая задача — калибровочная

Дешёвая, быстрая, с нулевым риском для существующего кода, и результат проверяется объективно. Даёт понять, справляется ли исполнитель, до того как ему доверят control plane.

Задача A — гигиена репозитория и цепочки поставки · до одного дня

Только новые файлы и .github/**. Ни одного файла, который трогает ветка B-3R.

  1. Запинить все GitHub Actions по commit SHA. Сейчас плавающие @v6, @v5, @v2 — содержимое шага может измениться без нашего ведома.
  2. .github/dependabot.yml для github-actions и nuget.
  3. Сузить permissions: contents: write в linux-release.yml и windows-release.yml до job'а публикации.
  4. SECURITY.md — куда сообщать об уязвимости, ожидаемое время ответа, что считается уязвимостью. Для инструмента безопасности его отсутствие — само по себе дефект.
  5. CHANGELOG.md в формате Keep a Changelog, заполнить по существующим тегам v0.1.0-alpha.1…5.
  6. CONTRIBUTING.md, CODEOWNERS, шаблоны issue и PR.
  7. SBOM (dotnet CycloneDX) как артефакт релиза.
  8. Удалить слитые ветки agent/remove-lightweight-server-references и codex/ttl-backup-acceptance.

Как я буду проверять результат: ни одна ссылка на action не содержит плавающего тега; permissions сужены именно в job'ах публикации, а не глобально; SECURITY.md содержит адрес и процедуру, а не заглушку; CHANGELOG соответствует реальным тегам, а не выдуман; CI зелёный; в TEST_EVIDENCE.md честно разделено локальное и CI; ревью получило текст задачи.

Если задача выполнена аккуратно и отчёт не приукрашен — переходим к содержательным задачам. Если в отчёте появятся непроверенные утверждения, это будет видно сразу и дёшево.


4. Дальнейшая очередь — Горизонт 0

Порядок обязательный. Горизонт закрывается целиком, Горизонт 1 не начинается до этого.

Задача B — завершить B-3R · зависит от решения по п. 0.1

Контракт: B3R_SPEC.md (выдан ранее, принят исполнителем как authoritative).

По состоянию на 04.08 закрыто: R3 полностью (lookup_node_ip читает статус, reserved → exit 80, active с битым IP → 78) и R1 на уровне отдельной мутации (VerifyExactFactualCountAsync считает записи через link-list, условие if (persisted) вокруг верификации снято).

Осталось:

  • пакетная финальная верификация: сейчас 1 + k вызовов link-list, требуется ровно два — стартовый и один финальный на все затронутые ключи;
  • класс Deferred и инвариант Converged + Failed + Deferred == Examined; PendingActivation — это Deferred, а не Failed, и он не блокирует потребление marker, иначе один зарезервированный Node вернёт бесконечный цикл проходов;
  • R4: именованный DTO в source-generated контексте вместо анонимного типа для orphan audit, с проверкой на опубликованном trimmed-артефакте;
  • R5: Linux integration test на fact-first протокол, с обязательным прогоном на Linux;
  • R6: убрать fail-open default у ILinkPolicyApplier.ListRulesAsync;
  • R7: форматирование вложенных lock-scope;
  • дополнительно: мусор в поле статуса nodes.tsv должен давать 78, а не 80 — повреждённое состояние не то же самое, что ожидаемое.

Готово, когда: PR создан, Linux CI зелёный впервые для этой ветки, merge выполнен.

Задача C — жизненный цикл сертификатов

CertificateAuthority.cs:55 выдаёт клиентские сертификаты на год, автопродления нет. Через год после развёртывания парк отваливается одновременно, и восстановление потребует ручной перерегистрации каждого Node.

  • срок клиентского сертификата 3090 дней, значение в конфигурации с валидацией;
  • автопродление Agent за треть срока до истечения через существующий mTLS-канал: новый CSR, выдача, атомарная замена agent.pfx, откат при неудаче;
  • продление Operator-сертификата Desktop с уведомлением пользователя;
  • событие certificate.expiring в поток событий;
  • документированная процедура ротации Control CA и повторной регистрации парка — сейчас её нет;
  • тесты: продление до истечения, недоступный Hub в момент продления, отказ при отозванном сертификате.

Файлы CertificateAuthority.cs, CertificateLifecycleService.cs, AgentClient.cs веткой B-3R не затронуты — задачу можно вести параллельно задаче B.

Задача D — роль Monitor в bootstrap

SSH-мониторинг — функция, ради которой существует Desktop, — не имеет серверной части. В bootstrap нет install-monitor, forced-command скрипт не поставляется, а парсер SshMonitorService.QueryAsync ожидает ключи PROTOCOL, CPU_COUNT, MEM_AVAILABLE_KB, DISK_INODES_TOTAL, которых в репозитории никто не производит.

  • действия install-monitor PUBLIC_KEY и uninstall-monitor;
  • пользователь ochenstarik-monitor: nologin, без пароля, без sudo;
  • /usr/local/libexec/ochenstarik-smm-metrics, root-owned 0755, выдающий ровно снимок из docs/installer-contract.md §7 и read-only mesh status;
  • authorized_keys с command="…",restrict,no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding;
  • идемпотентность повторного запуска и корректное удаление;
  • контрактный тест формата снимка, общий для скрипта и парсера Desktop.

Bootstrap-скрипт затронут веткой B-3R — делать после merge задачи B.

Задача E — подписанная поставка

Bootstrap сверяет ARCHIVE.sha256, лежащий рядом с архивом в том же релизе, а manifest не подписан и содержит только хэш самого bootstrap. Кто может опубликовать релиз — ставит произвольный root-код на весь парк через update-agent.

  • manifest v2: хэши всех артефактов, версии Control/Agent/helper/Desktop, минимальные совместимые версии, helper_protocol;
  • подпись cosign sign-blob keyless либо minisign; публичный ключ или issuer вшит константой в bootstrap и Desktop, а не скачивается вместе с релизом;
  • действие verify-manifest; verify_archive сверяет хэш с manifest, а не с соседним файлом; старый путь только под SMM_ALLOW_UNSIGNED=1;
  • отказ update-control и update-agent при несовместимых версиях — требование docs/installer-contract.md §6, не выполненное до сих пор;
  • PROGRAM_VERSION из тега вместо 0.2.0-dev;
  • отсутствие инструмента проверки подписи — отказ, не предупреждение;
  • негативные тесты в CI: изменённый байт архива, подменённый хэш в manifest, manifest без подписи.

Задача F — инженерная оснастка

  • Directory.Build.props: Nullable, TreatWarningsAsErrors, EnableNETAnalyzers, AnalysisLevel latest-recommended, детерминированная сборка;
  • Directory.Packages.props и RestorePackagesWithLockFile с коммитом lock-файлов — сейчас сборки невоспроизводимы, что противоречит требованию закреплённой поставки;
  • разделить тесты на Core.Tests, Control.Tests, Agent.Tests, Helper.Tests: сегодня LinuxMetricsTests, MetricBufferTests и ProvisioningHelperTests лежат в проекте Control;
  • тесты round-trip сериализации контрактов: при PublishTrimmed=true молчаливая потеря поля не ловится ничем.

TreatWarningsAsErrors включать после merge задачи B, иначе сломает незавершённую ветку.

Гейт Горизонта 0

Чистый сервер ставится из подписанного релиза одной командой, регистрируется одноразовым кодом, попадает под мониторинг без ручной правки authorized_keys, и после перезагрузки Hub и Node фактическое состояние Links совпадает с желаемым — измеренное связностью на реальной топологии.

Последнее не может закрыть ни один исполнитель. Это единственное, что зависит только от выдачи доступов, и оно дешевле любой задачи в этом плане.


5. Горизонт 1 и далее

Не выдавать до закрытия гейта Горизонта 0. Состав и порядок — по docs/product-horizons.md и разделу «Горизонт 1» документа smm-codex-plan-2026-08-04.md: каркас IProvisioningModule первым, затем модули по одному, политики подтверждения, миграция SSH, alert engine, Telegram только на чтение, наблюдение Docker и systemd, Backup Manager.

Ключевое правило переноса: не добавлять второй provisioning-модуль копированием timezone-исполнителя. Сначала каркас, иначе шесть копий логики backup → mutate → verify → rollback.


6. Как оценивать исполнителя

По задаче A смотреть на четыре вещи, в порядке важности:

  1. Честность отчёта. Разделены ли локальные проверки, CI и то, что не запускалось. Появление в отчёте непроверенных утверждений — худший признак из возможных, потому что обесценивает все последующие отчёты.
  2. Соответствие постановке, а не её пересказ. Выполнены ли все восемь пунктов, а не пять удобных.
  3. Отсутствие расползания. Не тронуты ли файлы вне области задачи.
  4. Качество ревью. Получил ли независимый ревьюер полный текст задачи и нашёл ли что-нибудь, кроме опечаток.

Если задача A пройдена — давать задачу C (сертификаты): она содержательная, файлы свободны, и результат тоже проверяется объективно. Задачу B (завершение B-3R) давать только после того, как решён вопрос 0.1 и подтверждено, что исполнитель понимает контракт: это самая тонкая часть системы, там уже дважды находили блокирующие дефекты.