From d52bb0e515f0af5fa8dccd69f266a9f6dc9536eb Mon Sep 17 00:00:00 2001 From: Ochenstarik Date: Wed, 19 Aug 2026 16:29:20 +0700 Subject: [PATCH 1/8] =?UTF-8?q?chore(agents):=20=D0=B7=D0=B0=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F,=20=D0=BE=D1=82=D1=87=D1=91=D1=82=D1=8B=20?= =?UTF-8?q?=D0=B8=20=D1=80=D0=B0=D0=B7=D0=B1=D0=BE=D1=80=20PR=20#63?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Задания и отчёты по актуализации проекта согласно agents/README.md: синхронизация git-состояния, обновление зависимостей, разбор PR #63. Правок workflow ветка не несёт: обновления GitHub Actions доставляются слиянием PR Dependabot #44 и #46, чтобы не применить одно и то же дважды. PR #45 (cosign-installer) не принят — релизный workflow на pull request не выполняется, поэтому зелёные проверки его не покрывают. Также добавлена записка передачи состояния, закоммитить её разрешил владелец. Co-Authored-By: Claude Opus 5 --- agents/claude/done/2026-08-18-deps-update.md | 151 ++++++++++++++++++ agents/claude/done/2026-08-18-git-sync.md | 104 ++++++++++++ .../2026-08-18-review-pr63-console-links.md | 116 ++++++++++++++ agents/claude/inbox/2026-08-18-deps-update.md | 45 ++++++ agents/claude/inbox/2026-08-18-git-sync.md | 34 ++++ .../notes/2026-08-18-передача-состояния.md | 114 +++++++++++++ 6 files changed, 564 insertions(+) create mode 100644 agents/claude/done/2026-08-18-deps-update.md create mode 100644 agents/claude/done/2026-08-18-git-sync.md create mode 100644 agents/claude/done/2026-08-18-review-pr63-console-links.md create mode 100644 agents/claude/inbox/2026-08-18-deps-update.md create mode 100644 agents/claude/inbox/2026-08-18-git-sync.md create mode 100644 agents/claude/notes/2026-08-18-передача-состояния.md diff --git a/agents/claude/done/2026-08-18-deps-update.md b/agents/claude/done/2026-08-18-deps-update.md new file mode 100644 index 0000000..f4324d0 --- /dev/null +++ b/agents/claude/done/2026-08-18-deps-update.md @@ -0,0 +1,151 @@ +# Отчёт: обновление зависимостей GitHub Actions и NuGet + +- **Задание:** `../inbox/2026-08-18-deps-update.md` +- **Агент:** `claude` +- **Дата:** 2026-08-18 +- **Ветка / коммиты:** `claude/deps-update`. Правок workflow эта ветка не + несёт — см. «Как доставлено». + +## Что сделано + +Разобрано отставание зависимостей и проверены три открытых PR Dependabot по +GitHub Actions. Проверка была содержательной, а не сводилась к «CI зелёный». + +- `actions/download-artifact` v4.1.8 → v8.0.1 (PR #46). Затрагивает одну + точку — `linux-release.yml:256`; это была последняя старая ссылка в дереве, + `linux-platform-matrix.yml` уже использовал v8.0.1 (SHA `3e5f45b2…`). + Обновление приводит репозиторий к одной версии. +- `docker/setup-qemu-action` → v4.2.0 (PR #44). Одна точка, + `linux-control-agent.yml:83`; прежняя ссылка была закреплена по SHA + `c7c53464…` с комментарием `# v3` без минорной версии. +- `sigstore/cosign-installer` v3.5.0 → v4.1.2 (PR #45). **Не принят**, + причина в разделе «Вопросы к приёмке». + +Все три правки я предварительно применял локально и построчно сверял с +ветками Dependabot — совпадение полное. Затем правки из ветки сняты, чтобы +не применить одно и то же дважды: доставка идёт слиянием PR Dependabot. + +NuGet не обновлялся — см. «Что не сделано». + +## Как доставлено + +Решением владельца от 2026-08-18: сливаются PR #44 и #46, правки из этой +ветки сняты. В ветке остаются только задания, отчёты и записка передачи +состояния. PR #45 остаётся открытым. + +## Как проверено + +Сверка применённых правок с ветками Dependabot (до снятия правок): + +``` +$ git diff -- .github/ | grep -E '^[+-][^+-]' | sort > mine.lines +$ for b in dependabot/github_actions/actions/download-artifact-8.0.1 \ + dependabot/github_actions/sigstore/cosign-installer-4.1.2 \ + dependabot/github_actions/docker/setup-qemu-action-4.2.0; do + git diff origin/main...origin/$b -- .github/ + done | grep -E '^[+-][^+-]' | sort > pr.lines +$ diff pr.lines mine.lines +СОВПАДАЕТ построчно +``` + +Старых версий после применения в дереве не оставалось: + +``` +$ grep -rn "download-artifact@fa0a91b8\|cosign-installer@v3\|setup-qemu-action@c7c53464" .github/workflows/ +старых версий не осталось +``` + +YAML всех шести workflow разбирается: + +``` +$ for f in .github/workflows/*.yml; do python -c "import sys,yaml;yaml.safe_load(open(sys.argv[1],encoding='utf-8'));print('OK',sys.argv[1])" "$f"; done +OK .github/workflows/linux-control-agent.yml +OK .github/workflows/linux-platform-matrix.yml +OK .github/workflows/linux-release.yml +OK .github/workflows/release-verification.yml +OK .github/workflows/windows-build.yml +OK .github/workflows/windows-release.yml +``` + +Текущее состояние ветки — правок workflow нет: + +``` +$ git diff 23eb3f5 --stat -- .github/ +(пусто) +``` + +## Что не сделано + +**NuGet не обновлён — нет .NET SDK на машине.** + +``` +$ dotnet --version +bash: dotnet: command not found + +PS> Get-Command dotnet +dotnet not found on PATH +``` + +В `Directory.Build.props` включён `RestorePackagesWithLockFile=true`, в CI +сборка идёт с `-p:RestoreLockedMode=true`, и в дереве семь +`packages.lock.json`. Поднять версию в `Directory.Packages.props` без +пересборки lock-файлов — гарантированно уронить CI. Без SDK пересобрать их +нечем, поэтому файлы не тронуты. + +Отставание по данным `api.nuget.org` на 2026-08-18 (запрошены версии, +`dotnet list package --outdated` не запускался): + +| Пакет | В репозитории | Актуальная | +|-------|---------------|------------| +| Microsoft.AspNetCore.Authentication.Certificate | 10.0.10 | 10.0.11 | +| Microsoft.AspNetCore.Mvc.Testing | 10.0.10 | 10.0.11 | +| Microsoft.Data.Sqlite | 10.0.10 | 10.0.11 | +| Microsoft.Extensions.Configuration.* (4 пакета) | 10.0.10 | 10.0.11 | +| System.Security.Cryptography.ProtectedData | 10.0.0 | 10.0.11 | +| Microsoft.NET.ILLink.Tasks (`Directory.Build.props`) | 10.0.10 | 10.0.11 | +| Microsoft.Windows.SDK.BuildTools | 10.0.28000.2270 | 10.0.28000.2526 | +| Microsoft.Windows.SDK.BuildTools.WinApp | 0.4.0 | 0.6.0 | +| Microsoft.WindowsAppSDK | 2.2.0 | 2.4.0 | +| Microsoft.NET.Test.Sdk | 18.8.1 | 18.9.0 | +| xunit.v3 | 3.2.2 | 4.0.0 (мажорная) | +| xunit.runner.visualstudio | 3.1.5 | 4.0.0 (мажорная) | +| SQLitePCLRaw.bundle_e_sqlite3 | 3.0.5 | 3.0.5 — актуален | + +Открытых PR Dependabot по NuGet нет, хотя в `.github/dependabot.yml` +экосистема `nuget` настроена с недельным интервалом. Причина не определена. + +## Замечено рядом + +Вне границ задачи; предлагаю отдельными заданиями. + +1. **`sigstore/cosign-installer` закреплён тегом, а не SHA.** Все остальные + действия в репозитории закреплены по коммиту с комментарием версии; + cosign-installer — единственное исключение, и это единственное действие, + от которого зависит подпись релиза. Тег подвижен. +2. **`Microsoft.Windows.SDK.BuildTools.WinApp` 0.4.0** — версия ниже 1.0, + мажорных гарантий совместимости нет; переход на 0.6.0 делать отдельно. +3. **xunit 3 → 4 — мажорный переход** для двух пакетов, отдельной задачей + с прогоном тестов. + +## Вопросы к приёмке + +**PR #45 (`cosign-installer` 3.5.0 → 4.1.2) не принят к слиянию.** + +Зелёные проверки на #45 и #46 про релиз ничего не доказывают: +`linux-release.yml` запускается только по `push` тега `v*` и по +`workflow_dispatch` (строки 3–12), на pull request он не выполняется вовсе. +Мажорная смена installer меняет версию cosign у producer, а +`deploy/ochenstarik-server-monitor-manager.sh:34` фиксирует у consumer +`COSIGN_VERSION="v3.1.3"` с проверкой SHA-256. Какую версию cosign ставит +installer 4.1.2 по умолчанию — не проверял, это не определено. +`docs/release-policy.md` показывает четыре поломки контракта +producer/consumer по cosign: alpha.12, alpha.13, alpha.17, alpha.18. + +Предлагаю до слияния #45 прогнать `Release pipeline` через +`workflow_dispatch` на репетиционном теге — с оговоркой из +`agents/claude/notes/2026-08-18-передача-состояния.md`: репетиция идёт по +`refs/heads/main` и пропускает шаги под условием `refs/tags/*`, так был +сожжён alpha.19. Значит проверять нужно ещё и то, что нужные шаги вообще +исполнялись. + +Второй вопрос: обновлять ли NuGet отдельным заданием на машине с .NET SDK. diff --git a/agents/claude/done/2026-08-18-git-sync.md b/agents/claude/done/2026-08-18-git-sync.md new file mode 100644 index 0000000..e5bdb4b --- /dev/null +++ b/agents/claude/done/2026-08-18-git-sync.md @@ -0,0 +1,104 @@ +# Отчёт: синхронизация git-состояния репозитория + +- **Задание:** `../inbox/2026-08-18-git-sync.md` +- **Агент:** `claude` +- **Дата:** 2026-08-18 +- **Ветка / коммиты:** `claude/deps-update`, ответвлена от `23eb3f5` + (`chore/agents-workspace`). Изменений кода в рамках этой задачи нет. + +## Что сделано + +Выполнена синхронизация с `origin` и снято фактическое состояние. Файлы +репозитория этой задачей не менялись — сводить оказалось нечего. + +Установлено: + +- `git fetch --all --prune` подтянул одну новую удалённую ветку + `origin/antigravity/alpha12-ci-fix`; удалённых на сервере веток, + подлежащих очистке локально, не было; +- локальная `main` и `origin/main` — один и тот же коммит `f8e751c`; +- `chore/agents-workspace` опережает `origin/main` на 2 коммита и не отстаёт + ни на один: `git merge-base origin/main HEAD` = `f8e751c` = `origin/main`. + Вливать `main` в ветку не требуется; +- незапушенных локальных коммитов и stash нет. + +Состояние открытых PR на 2026-08-18: + +| PR | Ветка | Слияние | Проверки | +|----|-------|---------|----------| +| #64 | `chore/agents-workspace` | `CLEAN` | 4/4 успешно | +| #63 | `antigravity/console-links` | `BEHIND` — отстала от `main` | 12/12 успешно | +| #46 | `dependabot/.../download-artifact-8.0.1` | `CLEAN` | 4/4 успешно | +| #45 | `dependabot/.../cosign-installer-4.1.2` | `CLEAN` | 4/4 успешно | +| #44 | `dependabot/.../setup-qemu-action-4.2.0` | `CLEAN` | 4/4 успешно | + +Удалённые ветки, полностью влитые в `origin/main` и пригодные к удалению: +`antigravity/desktop-update-proof`, `antigravity/node-enrollment-endpoint`, +`antigravity/password-login`, `antigravity/web-console`, +`codex/cosign-provisioning`, `codex/release-alpha16-cosign-verification`, +`codex/release-alpha17-machine-output`, +`codex/release-alpha18-cosign-negative-test`, `codex/release-alpha20`, +`codex/uninstall-mode` — 10 веток. + +Не влита и при этом не имеет открытого PR: `antigravity/alpha12-ci-fix`. +Её назначение не определено. + +## Как проверено + +``` +$ git fetch --all --prune +From https://github.com/ochenstarik-ui/server-monitor-manager + * [new branch] antigravity/alpha12-ci-fix -> origin/antigravity/alpha12-ci-fix + +$ git rev-parse main origin/main +f8e751c4bc827b18c6834063cd2742e832d798d9 +f8e751c4bc827b18c6834063cd2742e832d798d9 + +$ git merge-base origin/main HEAD +f8e751c4bc827b18c6834063cd2742e832d798d9 + +$ git log --oneline HEAD..origin/main +(пусто) + +$ git log --oneline origin/main..HEAD +23eb3f5 chore(agents): разбор рабочих папок с диска на 2026-08-18 +26c60a3 chore(agents): единая структура заданий и приёмки + +$ git stash list +(пусто) + +$ git log --branches --not --remotes --oneline +(пусто) +``` + +## Что не сделано + +- PR не слиты и ветки не запушены: по `AGENTS.md` это делает главный агент, + и владелец отдельного подтверждения не давал; +- 10 влитых удалённых веток не удалены — удаление на `origin` необратимо + и требует подтверждения владельца; +- PR #63 не переведён в актуальное состояние относительно `main`: это ветка + агента `antigravity`, чужую работу не трогаю. + +## Замечено рядом + +Вне границ задачи; предлагаю отдельными заданиями. + +1. **CHANGELOG отстал на 14 релизов.** `CHANGELOG.md` заканчивается на + `v0.1.0-alpha.6` (2026-07-31), теги идут до `v0.1.0-alpha.20` + (2026-08-18). Секция `Unreleased` ссылается на давно слитые #10–#12. +2. **README называет неверную текущую версию.** `README.md:101` — + «`v0.1.0-alpha.14` is an early testing release». +3. **`docs/release-policy.md` доведён до alpha.19**, запись про alpha.20 + отсутствует, хотя документ ведёт построчную историю каждой версии. +4. **`docs/roadmap.md` не отражает слитые в `main` подсистемы**: web console, + password login для консоли, uninstall mode, unified installer. +5. **Ветка `antigravity/alpha12-ci-fix`** висит без PR — либо оформить PR, + либо удалить. + +## Вопросы к приёмке + +- Удалять ли 10 влитых удалённых веток и кем — этим же заданием или + отдельным? +- Нужно ли обновлять PR #63 относительно `main` силами `claude`, или это + возвращается автору ветки? diff --git a/agents/claude/done/2026-08-18-review-pr63-console-links.md b/agents/claude/done/2026-08-18-review-pr63-console-links.md new file mode 100644 index 0000000..6101ec2 --- /dev/null +++ b/agents/claude/done/2026-08-18-review-pr63-console-links.md @@ -0,0 +1,116 @@ +# Отчёт: разбор PR #63 «Link management и Event Journal в веб-консоли» + +- **Задание:** роль главного агента, подтверждена владельцем в чате 2026-08-18 +- **Агент:** `claude` (в роли главного агента) +- **Дата:** 2026-08-18 +- **Разбираемая работа:** PR #63, ветка `antigravity/console-links`, + коммит `051d917`; задание — + `agents/antigravity/inbox/from-smm-deliverables/smm-antigravity-task-console-links-2026-08-18.md`; + отчёт исполнителя — описание PR #63. + +## Что сделано + +Разбор по репозиторию, а не по отчёту: диф снят от базы слияния +`7c43977`, а не от `main`. + +## Как проверено + +``` +$ git merge-base origin/main origin/antigravity/console-links +7c43977fd137c2236f7fc100f5d972f4e5f2bcac + +$ git diff --stat 7c43977 origin/antigravity/console-links + src/ServerMonitorManager.Control/wwwroot/app.js | 722 +++++++++++++++++---- + src/ServerMonitorManager.Control/wwwroot/index.html| 179 ++++- + src/ServerMonitorManager.Control/wwwroot/style.css | 156 ++++- + tests/.../WebConsoleTests.cs | 45 +- + 4 files changed, 976 insertions(+), 126 deletions(-) +``` + +Границы задания соблюдены: `deploy/**`, релизные workflow и bootstrap-тесты +не затронуты, новых эндпоинтов нет. Заявленный в описании PR состав файлов +совпадает с фактическим. + +**Проверено и подтверждается:** + +- **XSS не найден.** `escapeHtml` (app.js:1045) экранирует пять сущностей + (`& < > " '`) и применён при каждой интерполяции в `innerHTML`, включая + payload событий (app.js:479), `lastError` (338) и `data-*`-атрибуты + (347–351). Непроэкранированных вставок пользовательских данных не найдено. +- **Разбор NDJSON корректен.** app.js:412–413 — `split('\n')` с + возвратом хвоста в буфер через `pop()`; разрыв события на границе чанка + не теряется и не портит разбор. +- **Переподключение не размножается.** `startEventStream` вызывается ровно + из двух мест (app.js:89 при инициализации и 431 по таймеру), в начале + функции прежний `AbortController` прерывается. Накопления параллельных + таймеров нет. +- **Журнал ограничен**: `MAX_EVENTS_IN_JOURNAL = 100`, `unshift` + `pop` + (app.js:437–439). Неограниченного роста в долгоживущей вкладке нет. + +## Замечания + +**1. Тесты не проверяют поведение — только строки в статическом HTML.** + +Оба теста (`WebConsoleHtmlContainsRequiredUiElementsAndWarning` и новый +`WebConsoleProvidesLinkManagementAndEventsJournal`) состоят из +`Assert.Contains("id=\"…\"", html)` по разметке. Они доказывают, что в +`index.html` есть элементы с нужными идентификаторами, и ничего больше. + +При этом 976 изменённых строк — почти целиком поведение на JavaScript: +создание Link, отключение, идемпотентность, разбор потока событий, +расчёт срока действия, разбор Problem Details. Ни одна из этих веток +тестом не покрыта. + +В описании PR «158 пройденных тестов» приведено как доказательство работы +управления Links. Это не доказательство: пройдёт и разметка с правильными +`id` при полностью нерабочем `app.js`. Соглашение 6 из +`agents/claude/notes/2026-08-18-передача-состояния.md` — «зелёный CI не +означает работающую машину» — здесь применимо буквально. + +**2. Обновление дашборда не троттлится (app.js:444–448).** + +```js +const eventType = (ev.type || '').toLowerCase(); +if (eventType.startsWith('link.') || eventType.startsWith('agent.')) { + loadDashboardData(false); +} +``` + +Каждое событие `link.*` или `agent.*` вызывает `loadDashboardData`, а тот +делает два запроса — `/api/v1/control/agents` и `/api/v1/control/links` +(app.js:230–233). Ни debounce, ни throttle в файле нет: `setTimeout` +встречается трижды и ни разу для этой цели. + +Согласование политик Links в Control работает непрерывно (`CHANGELOG.md`, +Unreleased, #11). Пачка событий согласования по флоту превращается в +двукратно умноженный поток запросов от каждой открытой вкладки консоли. +На одном узле незаметно, на флоте — усилитель нагрузки на Control. + +**3. Мелкое: запасной `generateUuid` на `Math.random()` (app.js:167).** + +Для ключа идемпотентности приемлемо — это не секрет. Отмечаю только чтобы +запасная ветка не была скопирована туда, где нужна криптостойкость. + +## Что не сделано + +- `dotnet build` и `dotnet test` не запускались: на машине нет .NET SDK + (`dotnet: command not found` и в Git Bash, и в PowerShell). Заявленные + в описании PR 158 пройденных тестов и зелёные прогоны CI я принимаю по + ссылкам на прогоны, а не по собственному запуску; +- консоль в браузере не открывалась, поведение вручную не проверялось; +- PR не слит: ветка отстала от `main` (`mergeStateStatus = BEHIND`), + и решение о слиянии за владельцем. + +## Решение + +Работа соответствует заданию по составу и границам, дефектов безопасности +в ней не найдено. К слиянию пригодна после обновления относительно `main`. + +Замечание 1 не блокирует слияние, но должно стать отдельным заданием: без +поведенческих тестов следующая правка `app.js` не будет ничем удержана. +Замечание 2 — отдельным заданием на исправление. + +## Вопросы к приёмке + +- Обновлять ветку относительно `main` силами `claude` или возвращать автору? +- Выпускать ли задания по замечаниям 1 и 2 сразу, или после слияния #63. diff --git a/agents/claude/inbox/2026-08-18-deps-update.md b/agents/claude/inbox/2026-08-18-deps-update.md new file mode 100644 index 0000000..8cb7c6e --- /dev/null +++ b/agents/claude/inbox/2026-08-18-deps-update.md @@ -0,0 +1,45 @@ +# Обновление зависимостей: GitHub Actions и NuGet + +- **Кому:** `claude` +- **Дата:** 2026-08-18 +- **От кого:** владелец проекта (задание получено в чате: «актуализируй проект», + уточнено выбором «Обновить зависимости») +- **Ветка:** `claude/deps-update` +- **Файл отчёта:** `../done/2026-08-18-deps-update.md` + +## Что нужно сделать + +Закрыть отставание зависимостей: + +1. GitHub Actions — три открытых PR от Dependabot (#44 `docker/setup-qemu-action` + 3.7.0 → 4.2.0, #45 `sigstore/cosign-installer` 3.5.0 → 4.1.2, + #46 `actions/download-artifact` 4.1.8 → 8.0.1). +2. NuGet — версии в `Directory.Packages.props` и `Directory.Build.props` + против актуальных на nuget.org. + +## Границы + +Не мержить PR Dependabot и не пушить ветку без подтверждения владельца. +Не менять способ закрепления действий (tag → SHA) — это отдельная задача, +даже если несоответствие очевидно. Не править код проекта, документацию +и CHANGELOG. + +## Как проверить результат + +- Обновлённые SHA в `.github/workflows/` совпадают с SHA из соответствующих + веток Dependabot: `git diff origin/main...origin/dependabot/...`; +- `grep -rn "uses:" .github/workflows/` — в дереве не осталось старых версий; +- для NuGet: `dotnet list package --outdated` и восстановление + `packages.lock.json` (`RestorePackagesWithLockFile=true`, + в CI `-p:RestoreLockedMode=true`). + +## Контекст и ограничения + +Релизная подпись зависит от cosign: `deploy/ochenstarik-server-monitor-manager.sh` +закрепляет потребительский `COSIGN_VERSION="v3.1.3"` с проверкой SHA-256, +а CI ставит cosign через `sigstore/cosign-installer` без закрепления версии +cosign. `docs/release-policy.md` (alpha.17, alpha.18) описывает, что контракт +producer/consumer по cosign уже ломался. Смена версии installer — решение +владельца, не самостоятельное. + +Наличие .NET SDK на рабочей машине на момент постановки задачи не определено. diff --git a/agents/claude/inbox/2026-08-18-git-sync.md b/agents/claude/inbox/2026-08-18-git-sync.md new file mode 100644 index 0000000..f6552bd --- /dev/null +++ b/agents/claude/inbox/2026-08-18-git-sync.md @@ -0,0 +1,34 @@ +# Синхронизация git-состояния репозитория + +- **Кому:** `claude` +- **Дата:** 2026-08-18 +- **От кого:** владелец проекта (задание получено в чате: «актуализируй проект», + уточнено выбором «Синхронизировать git») +- **Ветка:** `claude/deps-update` +- **Файл отчёта:** `../done/2026-08-18-git-sync.md` + +## Что нужно сделать + +Установить фактическое расхождение локального репозитория и `origin`, свести +локальные ветки со свежим `main` и предъявить состояние открытых PR и +удалённых веток: что влито, что отстало, что можно удалять. + +## Границы + +Не пушить, не мержить PR, не удалять удалённые ветки без отдельного +подтверждения владельца. Не трогать ветки других агентов +(`antigravity/*`, `codex/*`, `hermes/*`). Не править документацию — +рассинхрон CHANGELOG/README/roadmap с фактическим состоянием релизов +вынесен из этой задачи и идёт в отчёт списком. + +## Как проверить результат + +- `git fetch --all --prune` — выполнен; +- `git rev-parse main origin/main` — совпадают; +- `git log --oneline HEAD..origin/main` — пусто (нечего вливать); +- `git branch -r --merged origin/main` — список влитых веток приведён в отчёте. + +## Контекст и ограничения + +`AGENTS.md`: в `main` пушит и принимает работу только главный агент. +Ветка ведётся с префиксом `claude/` согласно таблице в `agents/README.md`. diff --git a/agents/claude/notes/2026-08-18-передача-состояния.md b/agents/claude/notes/2026-08-18-передача-состояния.md new file mode 100644 index 0000000..55ea5a3 --- /dev/null +++ b/agents/claude/notes/2026-08-18-передача-состояния.md @@ -0,0 +1,114 @@ +# Передача состояния: как продолжить работу в новом чате + +Этот файл заменяет переписку. Он написан для того, чтобы новый чат начинался +с одного сообщения и не требовал пересказа истории. + +## Первое сообщение в новом чате + +> Репозиторий `C:\Users\Ochenstarik\Agent_projects\server-monitor-manager`, +> GitHub `ochenstarik-ui/server-monitor-manager`. +> Прочитай `agents/README.md` и `agents/claude/notes/2026-08-18-передача-состояния.md`, +> сверь состояние с GitHub и продолжай как главный агент: проверяешь работу +> Codex и Antigravity, пишешь им задания, мержишь и выпускаешь релизы. + +Больше ничего пересказывать не нужно: доска, задания, отчёты и архив лежат +в репозитории. + +## Где что лежит + +| Что | Где | +|---|---| +| Правила работы агентов | `agents/README.md` | +| Задания агенту | `agents//inbox/` | +| Отчёты агента | `agents//done/` | +| Принятые пары «задание — отчёт» | `agents/_accepted/ГГГГ-ММ-ДД-имя/` | +| Доска состояния (прежний формат) | `agents/_salvage-2026-08-18/smm-deliverables/README.md` | +| Архив закрытых заданий | `agents/_salvage-2026-08-18/smm-deliverables/Старые задачи/` | +| Инструкция владельцу по серверам | `agents/_salvage-2026-08-18/smm-deliverables/smm-cleanup-and-install-2026-08-15.md` | + +Доску стоит перенести из `_salvage` в постоянное место — она живая, а не архив. + +## Состояние на 2026-08-18 + +- `main` — `f8e751c`, слит PR #62 `codex/release-alpha20`; +- последний релиз — `v0.1.0-alpha.20`; +- открыты: PR #63 `antigravity/console-links` (управление Links в консоли), + PR #64 `chore/agents-workspace` (эта самая схема папок), плюс dependabot; +- ветка `claude/deps-update` содержит незакоммиченные правки двух workflow + и два новых задания в `agents/claude/inbox/`. + +### Сожжённые номера версий + +`alpha.10`, `alpha.11`, `alpha.19` — теги созданы, `Release pipeline` упал, +релизы не опубликованы, номера не переиспользуются. + +`alpha.19` сожжён при мне и по процедурной дыре, а не по вине исполнителя: +шаг `Package bootstrap` сверяет `DEFAULT_RELEASE_TAG` в `deploy/smm-setup.sh` +с выпускаемым тегом, но весь блок закрыт условием `refs/tags/*`, поэтому +репетиция через `workflow_dispatch` идёт по `refs/heads/main` и эту сверку +пропускает. Репетиция была зелёной, тег упал. + +**Вывод, который дороже самого случая:** репетиция, не покрывающая шаги, +исполняемые только на теге, не является репетицией. Проверять это до +следующего выпуска. + +## Рабочие соглашения + +Выведены из происшествий, а не из общих соображений. + +1. **Задание содержит только предстоящую работу.** Файлы, начинавшиеся + с описания уже сделанного, исполнитель принимал за отчёт о выполнении: + Codex ответил «задание уже выполнено, PR #58» вместо работы над + невыполненной частью. Сделанное живёт на доске, а не в задании. +2. **Отчёт — раздел в описании PR.** Отдельный файл с отчётом результатом + не является. Antigravity однажды сдал только такой файл, не создав ни ветки, + ни PR. +3. **Проверять по репозиторию, а не по отчёту.** Смотреть диф от базы слияния, + а не от `main`: отставшая ветка в обычном дифе выглядит так, будто удаляет + чужую работу. +4. **Критерий приёмки должен быть достижим.** «Проверка запустилась + автоматически» была недостижима: событие от `GITHUB_TOKEN` не запускает + другие workflow. Это дефект задания, а не исполнителя. +5. **Границы областей прописывать явно.** Codex — `deploy/**`, релизный + пайплайн, проверка релиза. Antigravity — `src/**`, консоль, тесты Control + и Desktop. Пересечение областей ломает параллельную работу. +6. **Зелёный CI не означает работающую машину.** Так найдены: отсутствующий + cosign, права на каталог mesh, отдача ассетов из ресурсов сборки. Каждый раз + тест подставлял временный путь и проходил, а на сервере отказывало. +7. **Команды владельцу помечать, где выполнять**: 🖥 на Windows, 🐧 на сервере. + Путаница машин стоила нескольких заходов. +8. **Долгие загрузки — с индикатором.** Молчащий `curl -fsSL` на 24 МБ дважды + принят за зависание и прерван. + +## Живая установка + +Проверено на настоящих машинах, а не в CI. + +- **Hub** `178.212.13.102` (`host1885995-3.hostland.pro`), Ubuntu 24.04 x86_64, + поставлен из `v0.1.0-alpha.14`; +- отпечаток CA: + `EB:05:E5:16:42:EE:97:28:C2:E9:EA:6F:3E:48:3C:0C:1C:1E:02:E0:ED:9B:AF:7B:BF:24:2C:19:D4:4B:11:C4`; +- публичный ключ WireGuard Hub: `AjN8XwPB11bRQa0fO5ljPlAWc0FxU+fxbeUT8AZczHk=`; +- **Node `ai-agent`** — `vm1957808.vds.chsl.one`, адрес `10.77.0.2`, mesh собран, + ping 7.6 мс. На этой машине работает 3x-ui и он не пострадал; +- свободных серверов больше нет. `tests/acceptance/three-server-mesh.sh` требует + Hub и три узла: источник и две цели, потому что смысл проверки в том, что + к одной цели доступ по Link открыт, а ко второй закрыт. На двух машинах + это не проверить; +- WSL под узлы не годится: все дистрибутивы WSL2 делят один сетевой стек, + два `smm0` с разными адресами не поднять. Проверено экспериментом. + +**Физическая приёмка — единственный пункт Горизонта 0, не закрываемый кодом.** + +## Что важно знать про продукт + +- подпись релиза проверяется настоящим материалом с обеих сторон: установкой + на чистый runner (Linux) и `UpdateService` (Windows), автоматически на каждом + релизе; +- проверка подписи требует исходящего доступа к службам sigstore; в закрытом + контуре установка зависнет; +- таблица nftables `inet ochenstarik_smm` цепляется только к хуку `forward` + и только к трафику `smm0 → smm0`. Хука `input` в ней нет, политика `accept`. + Поэтому установка на сервер с 3x-ui безопасна — проверено на живой машине; +- опубликованный тег неизменяем, ассеты не заменяются: исправление выпускается + следующим номером. -- 2.45.2 From 8ebb946645efcba2abea6506c500edef7f707ea6 Mon Sep 17 00:00:00 2001 From: Ochenstarik Date: Wed, 19 Aug 2026 16:46:59 +0700 Subject: [PATCH 2/8] =?UTF-8?q?chore(agents):=20=D0=B7=D0=B0=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20Antigravity=20=D0=BF=D0=BE=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=B1=D0=BE=D1=80=D0=B0=20PR=20#63?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Два задания по замечаниям разбора: поведенческие тесты веб-консоли вместо проверок строк в статическом HTML и троттлинг обновления дашборда по событиям. В обоих критерий приёмки требует чисел или показанного отказа теста, а не формулировки «работает». Co-Authored-By: Claude Opus 5 --- .../2026-08-19-console-behaviour-tests.md | 67 +++++++++++++++++++ .../2026-08-19-console-events-throttle.md | 59 ++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 agents/antigravity/inbox/2026-08-19-console-behaviour-tests.md create mode 100644 agents/antigravity/inbox/2026-08-19-console-events-throttle.md diff --git a/agents/antigravity/inbox/2026-08-19-console-behaviour-tests.md b/agents/antigravity/inbox/2026-08-19-console-behaviour-tests.md new file mode 100644 index 0000000..c7e05e6 --- /dev/null +++ b/agents/antigravity/inbox/2026-08-19-console-behaviour-tests.md @@ -0,0 +1,67 @@ +# Поведенческие тесты веб-консоли + +- **Кому:** `antigravity` +- **Дата:** 2026-08-19 +- **От кого:** главный агент (`claude`), по разбору PR #63 — + `agents/claude/done/2026-08-18-review-pr63-console-links.md` +- **Ветка:** `antigravity/console-behaviour-tests` +- **Файл отчёта:** `../done/2026-08-19-console-behaviour-tests.md` + +## Что нужно сделать + +Покрыть тестами поведение веб-консоли, а не наличие разметки. + +Сейчас `tests/ServerMonitorManager.Control.Tests/WebConsoleTests.cs` состоит +из проверок вида `Assert.Contains("id=\"create-link-btn\"", html)`. Такие +тесты проходят и при полностью нерабочем `app.js`: они доказывают, что в +`index.html` есть элемент с нужным идентификатором, и ничего больше. При этом +в PR #63 977 строк изменений — почти целиком логика на JavaScript. + +Нужны тесты, падающие при поломке поведения. Как минимум: + +1. **Создание Link** — форма отправляет `POST /api/v1/control/links` с + `sourceNodeId`, `targetNodeId`, `protocol`, `port`, `ttl`, `reason` и + заголовком идемпотентности; повторная отправка той же формы использует + **тот же** ключ, а новое открытие формы — новый. +2. **Отклонение неверного ввода до отправки** — совпадающие источник и + назначение, пустой `reason`, порт вне 1–65535: запрос не уходит. +3. **Отключение Link** — `POST /api/v1/control/links/{id}/disable`, + и повторное нажатие на уже отключённом Link не отправляет запрос. +4. **Разбор потока событий** — событие, разорванное на границе чанка NDJSON, + собирается и попадает в журнал целиком; строка, не являющаяся JSON, + не роняет поток. +5. **Ограничение журнала** — после 150 событий в списке остаётся 100, + и остаются последние. +6. **Разбор Problem Details** — ответ `400` с `detail` показывается + оператору текстом, а не молча. + +Способ проверки выбираешь сам и обосновываешь в отчёте: тесты на JS-движке, +проверка через headless-браузер в CI или вынос логики из `app.js` в +тестируемый модуль. Требование одно: тест должен падать, когда поведение +сломано. Если для этого нужна новая зависимость или шаг в CI — предложи в +отчёте, не добавляй молча. + +## Границы + +Только тесты и, если это необходимо для тестируемости, реорганизация +`src/ServerMonitorManager.Control/wwwroot/app.js` без изменения поведения. +Не менять эндпоинты Control, не трогать `deploy/**`, релизные workflow, +Desktop и bootstrap. Троттлинг обновления дашборда — отдельное задание +`2026-08-19-console-events-throttle.md`, здесь его не делать. + +## Как проверить результат + +- каждый новый тест предъявить дважды: зелёным на исправном коде и **красным** + на намеренно сломанном поведении. В отчёт — вывод обоих прогонов. Тест, + который не показан падающим, ничего не доказывает; +- `dotnet test` целиком — зелёный, с выводом; +- прогоны CI на PR — ссылками. + +## Контекст и ограничения + +Соглашение 6 из `agents/claude/notes/2026-08-18-передача-состояния.md`: +зелёный CI не означает работающую машину. Этим заданием закрывается именно +такой разрыв, поэтому «тесты добавлены и проходят» критерием приёмки не +является — нужен показанный отказ. + +Формат отчёта — раздел в описании PR плюс файл в `done/`. diff --git a/agents/antigravity/inbox/2026-08-19-console-events-throttle.md b/agents/antigravity/inbox/2026-08-19-console-events-throttle.md new file mode 100644 index 0000000..1d84247 --- /dev/null +++ b/agents/antigravity/inbox/2026-08-19-console-events-throttle.md @@ -0,0 +1,59 @@ +# Троттлинг обновления дашборда по событиям + +- **Кому:** `antigravity` +- **Дата:** 2026-08-19 +- **От кого:** главный агент (`claude`), по разбору PR #63 — + `agents/claude/done/2026-08-18-review-pr63-console-links.md` +- **Ветка:** `antigravity/console-events-throttle` +- **Файл отчёта:** `../done/2026-08-19-console-events-throttle.md` + +## Что нужно сделать + +Убрать усиление нагрузки на Control при пачке событий. + +В `src/ServerMonitorManager.Control/wwwroot/app.js` обработчик события +делает так: + +```js +const eventType = (ev.type || '').toLowerCase(); +if (eventType.startsWith('link.') || eventType.startsWith('agent.')) { + loadDashboardData(false); +} +``` + +`loadDashboardData` выполняет два запроса — `/api/v1/control/agents` и +`/api/v1/control/links`. Ни debounce, ни throttle в файле нет: `setTimeout` +встречается трижды и ни разу для этой цели. Согласование политик Links в +Control работает непрерывно (`CHANGELOG.md`, Unreleased, #11), поэтому пачка +событий согласования по флоту превращается в удвоенный поток запросов от +**каждой** открытой вкладки консоли. + +Нужно свести пачку событий к одному обновлению. Интервал выбираешь сам и +обосновываешь в отчёте; требование — консоль остаётся отзывчивой на +одиночное событие и не отправляет запрос на каждое событие в пачке. +Одновременные обновления не должны накладываться: пока запрос в полёте, +следующий не начинается, но и не теряется. + +## Границы + +Только `app.js`. Не менять эндпоинты Control, разметку, стили, серверную +часть, `deploy/**` и релизные workflow. Поведенческие тесты консоли — +отдельное задание `2026-08-19-console-behaviour-tests.md`. + +## Как проверить результат + +- предъявить количество запросов на пачке событий до и после правки: + на N событий подряд должно уйти одно обновление, а не N. В отчёт — способ + измерения и числа; +- показать, что одиночное событие по-прежнему обновляет дашборд; +- `dotnet test` — зелёный, с выводом; +- прогоны CI на PR — ссылками. + +«Стало лучше» без чисел результатом проверки не является. + +## Контекст и ограничения + +Дефект найден чтением кода, а не наблюдением на живой машине: подтверждения +с работающего Hub у меня нет, объём эффекта не измерен. Если при измерении +окажется, что усиления нет, — так и напиши в отчёте с числами; это +допустимый результат, а не провал задания. -- 2.45.2 From 771c252e794da2840fa1b4818be4dbdd74b5805d Mon Sep 17 00:00:00 2001 From: Ochenstarik Date: Thu, 20 Aug 2026 00:11:33 +0700 Subject: [PATCH 3/8] =?UTF-8?q?chore(agents):=20=D0=BF=D1=80=D0=B8=D1=91?= =?UTF-8?q?=D0=BC=D0=BA=D0=B0=20PR=20#63=20=D0=B8=20=D0=B7=D0=B0=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B5=20Codex=20=D0=BF=D0=BE=20cosign?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Пара «задание — разбор» по PR #63 перенесена в agents/_accepted/ с основанием приёмки и перечнем того, чего приёмка не доказывает: тесты главным агентом не запускались, на машине приёмки нет .NET SDK. Задание Codex требует определить версию cosign у installer 4.1.2, сойтись с потребителем по формату подписи и предъявить прогон релизного пути с перечнем шагов, пропущенных при репетиции. Co-Authored-By: Claude Opus 5 --- .../2026-08-19-console-links/ACCEPTANCE.md | 44 ++++++++++++ .../review-by-claude.md} | 0 .../2026-08-19-console-links/task.md} | 0 .../2026-08-19-cosign-installer-rehearsal.md | 69 +++++++++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 agents/_accepted/2026-08-19-console-links/ACCEPTANCE.md rename agents/{claude/done/2026-08-18-review-pr63-console-links.md => _accepted/2026-08-19-console-links/review-by-claude.md} (100%) rename agents/{antigravity/inbox/from-smm-deliverables/smm-antigravity-task-console-links-2026-08-18.md => _accepted/2026-08-19-console-links/task.md} (100%) create mode 100644 agents/codex/inbox/2026-08-19-cosign-installer-rehearsal.md diff --git a/agents/_accepted/2026-08-19-console-links/ACCEPTANCE.md b/agents/_accepted/2026-08-19-console-links/ACCEPTANCE.md new file mode 100644 index 0000000..16e7704 --- /dev/null +++ b/agents/_accepted/2026-08-19-console-links/ACCEPTANCE.md @@ -0,0 +1,44 @@ +# Приёмка: управление Links и журнал событий в веб-консоли + +- **Исполнитель:** `antigravity` +- **Принял:** `claude` (главный агент) +- **Дата приёмки:** 2026-08-19 +- **PR:** #63, слит коммитом `6115ed0` в `main` + +## Состав пары + +| Файл | Что это | +|------|---------| +| `task.md` | задание, было `agents/antigravity/inbox/from-smm-deliverables/smm-antigravity-task-console-links-2026-08-18.md` | +| `review-by-claude.md` | разбор главного агента, был `agents/claude/done/2026-08-18-review-pr63-console-links.md` | + +Отдельного файла отчёта исполнителя нет: отчёт оформлен разделом в описании +PR #63, как принято в проекте. + +## Основание приёмки + +Диф снят от базы слияния `7c43977`. Границы задания соблюдены: 4 файла, +`deploy/**`, релизные workflow и bootstrap-тесты не затронуты, новых +эндпоинтов Control нет. Дефектов безопасности не найдено: экранирование в +консоли сплошное, разбор NDJSON держит границу чанка, журнал ограничен, +переподключение не размножает таймеры. Подробности — в `review-by-claude.md`. + +Перед слиянием ветка обновлена относительно `main` (коммит `2459660`), +проверки `build` и `build-and-test` пройдены на обновлённой базе. + +## Принято с открытыми замечаниями + +Два замечания разбора в код не вносились и слияние не блокировали. По ним +выпущены отдельные задания: + +- `agents/antigravity/inbox/2026-08-19-console-behaviour-tests.md` — + тесты проверяют строки в статическом HTML, а не поведение; +- `agents/antigravity/inbox/2026-08-19-console-events-throttle.md` — + обновление дашборда по событиям не троттлится. + +## Чего приёмка не доказывает + +`dotnet build` и `dotnet test` главным агентом не запускались: на машине +приёмки нет .NET SDK. Заявленные исполнителем 158 пройденных тестов и +зелёные прогоны CI приняты по ссылкам на прогоны. Консоль в браузере не +открывалась, поведение вручную не проверялось. diff --git a/agents/claude/done/2026-08-18-review-pr63-console-links.md b/agents/_accepted/2026-08-19-console-links/review-by-claude.md similarity index 100% rename from agents/claude/done/2026-08-18-review-pr63-console-links.md rename to agents/_accepted/2026-08-19-console-links/review-by-claude.md diff --git a/agents/antigravity/inbox/from-smm-deliverables/smm-antigravity-task-console-links-2026-08-18.md b/agents/_accepted/2026-08-19-console-links/task.md similarity index 100% rename from agents/antigravity/inbox/from-smm-deliverables/smm-antigravity-task-console-links-2026-08-18.md rename to agents/_accepted/2026-08-19-console-links/task.md diff --git a/agents/codex/inbox/2026-08-19-cosign-installer-rehearsal.md b/agents/codex/inbox/2026-08-19-cosign-installer-rehearsal.md new file mode 100644 index 0000000..3e7a9cb --- /dev/null +++ b/agents/codex/inbox/2026-08-19-cosign-installer-rehearsal.md @@ -0,0 +1,69 @@ +# Доказать или отклонить обновление cosign-installer до 4.1.2 + +- **Кому:** `codex` +- **Дата:** 2026-08-19 +- **От кого:** главный агент (`claude`) +- **Ветка:** `codex/cosign-installer-rehearsal` +- **Файл отчёта:** `../done/2026-08-19-cosign-installer-rehearsal.md` + +## Что нужно сделать + +Открыт PR #45: `sigstore/cosign-installer` 3.5.0 → 4.1.2 в +`.github/workflows/linux-release.yml`, два вхождения (строки 26 и 253). +Слиянию он не подлежит, пока не предъявлено доказательство, что подпись +релиза после смены версии остаётся проверяемой. Нужно это доказательство — +либо обоснованный отказ от обновления. + +Ответить требуется на три вопроса, каждый — фактом, а не рассуждением: + +1. **Какую версию cosign ставит `cosign-installer@v4.1.2` по умолчанию.** + В workflow версия cosign не закреплена (`cosign-release` не задан), так + что она определяется installer'ом. Сейчас это не определено. +2. **Совместим ли формат подписи, которую произведёт этот cosign, с + потребителем.** `deploy/ochenstarik-server-monitor-manager.sh:34` + закрепляет `COSIGN_VERSION="v3.1.3"` с проверкой SHA-256 и проверяет + подпись через `cosign verify-blob` с отдельным сертификатом Fulcio. + Producer и consumer должны сойтись по формату. +3. **Проходит ли полный релизный путь.** Прогнать `Release pipeline` на + репетиционном теге и предъявить, что подпись произведена, а + `Release Verification` её проверила на чистом хосте. + +## Границы + +Только `.github/workflows/linux-release.yml`, `deploy/**` и релизные тесты. +Не трогать `src/**`, консоль, Desktop и `agents/` кроме своих папок. +Не выпускать настоящий релиз и не двигать существующие теги. + +Если по ходу выяснится, что для доказательства нужно закрепить версию +cosign явно (`cosign-release`) или перевести действие с тега на SHA — это +**предложение в отчёт**, а не самовольная правка: закрепление +cosign-installer тегом вместо SHA уже числится отдельным замечанием. + +## Как проверить результат + +- ссылки на прогоны `Release pipeline` и `Release Verification` с + репетиционным тегом и их фактический итог; +- вывод шага, который печатает версию установленного cosign; +- вывод проверки подписи потребителем. + +**Отдельное требование, из-за которого задание и появилось.** Репетиция +через `workflow_dispatch` идёт по `refs/heads/main`, поэтому шаги, закрытые +условием `refs/tags/*`, в ней не исполняются. Так был сожжён `alpha.19`: +репетиция была зелёной, а на теге упала сверка `DEFAULT_RELEASE_TAG`. +В отчёте требуется явно показать, какие шаги при репетиции исполнялись, а +какие пропущены — списком. Зелёная репетиция без этого списка +доказательством не считается. + +## Контекст и ограничения + +`docs/release-policy.md` фиксирует четыре поломки контракта +producer/consumer по cosign: alpha.12 (подпись без сертификата Fulcio), +alpha.13 (то же), alpha.17 (cosign v3 потребовал явный bundle или legacy +detached-output), alpha.18 (исправление негативного теста под detached-output). +Пятая поломка обойдётся ещё в один сожжённый номер версии. + +Сожжённые номера — `alpha.10`, `alpha.11`, `alpha.19`; они не +переиспользуются. + +Приемлемый результат задания — «обновление отклонено, причина такая-то». +Неприемлемый — «обновил, CI зелёный». -- 2.45.2 From 28e447da0d42139e263062afcd04767d02d3ec63 Mon Sep 17 00:00:00 2001 From: Ochenstarik Date: Thu, 20 Aug 2026 16:32:25 +0700 Subject: [PATCH 4/8] =?UTF-8?q?chore(agents):=20=D0=B8=D0=B7=D0=BC=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=87=D0=B8=D1=81=D0=BB?= =?UTF-8?q?=D0=B0=20=D0=B2=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=82=D1=80=D0=BE=D1=82=D1=82=D0=BB=D0=B8=D0=BD?= =?UTF-8?q?=D0=B3=D1=83=20=D0=BA=D0=BE=D0=BD=D1=81=D0=BE=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Замечание воспроизведено на стенде: настоящие файлы консоли под локальным макетом Control API. Пачка из 15 накопленных событий при подключении к потоку даёт 22 обновления дашборда, то есть 44 запроса примерно за 0,1 секунды с одной вкладки. В установившемся режиме слияния соседних событий нет ни одного. В задании было написано, что эффект не измерен — исправлено. Туда же уточнение проверки: мерить нужно пачку, а не установившийся режим. В задание по тестам добавлен найденный при показе дефект текста: строка подтверждения направления заканчивается двумя точками. Co-Authored-By: Claude Opus 5 --- .../2026-08-19-console-behaviour-tests.md | 15 ++++++++++ .../2026-08-19-console-events-throttle.md | 29 +++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/agents/antigravity/inbox/2026-08-19-console-behaviour-tests.md b/agents/antigravity/inbox/2026-08-19-console-behaviour-tests.md index c7e05e6..ef11c7a 100644 --- a/agents/antigravity/inbox/2026-08-19-console-behaviour-tests.md +++ b/agents/antigravity/inbox/2026-08-19-console-behaviour-tests.md @@ -41,6 +41,21 @@ сломано. Если для этого нужна новая зависимость или шаг в CI — предложи в отчёте, не добавляй молча. +## Замечено при показе консоли + +Мелкий дефект текста, найденный при прогоне консоли на стенде. Исправить +здесь же, отдельного задания он не стоит. + +Строка подтверждения направления заканчивается двумя точками: + +``` +Открытие доступа: с узла «demo-hub» к узлу «demo-home», протокол TCP, порт 443, на 60 мин.. +``` + +Сокращение «мин.» уже содержит точку, и к нему добавляется точка +предложения. Тест из пункта 1 должен проверять эту строку целиком, тогда +дефект и не вернётся. + ## Границы Только тесты и, если это необходимо для тестируемости, реорганизация diff --git a/agents/antigravity/inbox/2026-08-19-console-events-throttle.md b/agents/antigravity/inbox/2026-08-19-console-events-throttle.md index 1d84247..6af2034 100644 --- a/agents/antigravity/inbox/2026-08-19-console-events-throttle.md +++ b/agents/antigravity/inbox/2026-08-19-console-events-throttle.md @@ -51,9 +51,32 @@ Control работает непрерывно (`CHANGELOG.md`, Unreleased, #11), «Стало лучше» без чисел результатом проверки не является. +## Измерение, уже проведённое + +Дефект найден чтением кода, но затем воспроизведён и измерен на стенде: +настоящие файлы консоли из `wwwroot` под локальным макетом Control API. +Числа получены из журнала сетевых запросов браузера. + +- **Установившийся режим.** Одно событие → одно `loadDashboardData` → два + запроса (`/agents` и `/links`). Слияния соседних событий нет ни одного. +- **Пачка при подключении.** Поток отдал 15 накопленных событий разом — + консоль выпустила 22 обновления дашборда, то есть **44 запроса примерно + за 0,1 секунды**. Это одна вкладка и четыре узла. +- **Побочный эффект.** Каждое обновление перестраивает `innerHTML` таблицы + Links целиком. Во время пачки ссылки на элементы строки становятся + недействительными, и таблица перестраивается под курсором оператора. + +Воспроизведение: открыть консоль под макетом Control, отдающим backlog +событий при подключении к `/api/v1/control/events`, и посмотреть журнал +сетевых запросов. + +Отсюда следует уточнение к проверке: измерять надо именно пачку, а не +установившийся режим — в установившемся режиме при одном событии в 6 секунд +разница незаметна. + ## Контекст и ограничения -Дефект найден чтением кода, а не наблюдением на живой машине: подтверждения -с работающего Hub у меня нет, объём эффекта не измерен. Если при измерении -окажется, что усиления нет, — так и напиши в отчёте с числами; это +Измерение сделано на макете API, а не на живом Hub: скорость поступления +событий на настоящем флоте не проверена. Если на живой машине окажется, что +пачек не бывает и усиления нет, — так и напиши в отчёте с числами; это допустимый результат, а не провал задания. -- 2.45.2 From 1e6348ff2beadbb7a74e530c0ab4cab2efa063e9 Mon Sep 17 00:00:00 2001 From: Ochenstarik Date: Thu, 20 Aug 2026 16:36:31 +0700 Subject: [PATCH 5/8] =?UTF-8?q?docs:=20=D0=B2=D0=BE=D1=81=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2=D0=B8=D1=82=D1=8C=20=D0=B8=D1=81=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D1=8E=20=D1=80=D0=B5=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B2=20CHANGELOG,=20policy=20=D0=B8=20roadmap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHANGELOG обрывался на alpha.6 от 2026-07-31 при тегах до alpha.20. Дописаны 14 версий по тегам и коммитам между ними; даты сверены с датами тегов, расхождений нет. Сожжённые alpha.10, alpha.11 и alpha.19 помечены как несопубликованные с указанием, чем упал пайплайн. Для опубликованных, но дефектных версий записан сам дефект, иначе CHANGELOG подсказывал бы ставить версию, которая не ставится. В release-policy добавлена запись про alpha.20. В roadmap дописано фактически поставленное: веб-консоль и её разделы, режим полного удаления сервера, объединённый установщик. README и переводы намеренно не тронуты: по release-policy строка статуса релиза принадлежит владельцу релиза, изменение запрошено заданием Codex. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 206 +++++++++++++++++- agents/claude/done/2026-08-20-docs-sync.md | 87 ++++++++ agents/claude/inbox/2026-08-20-docs-sync.md | 41 ++++ .../inbox/2026-08-20-readme-release-status.md | 52 +++++ docs/release-policy.md | 1 + docs/roadmap.md | 13 ++ 6 files changed, 399 insertions(+), 1 deletion(-) create mode 100644 agents/claude/done/2026-08-20-docs-sync.md create mode 100644 agents/claude/inbox/2026-08-20-docs-sync.md create mode 100644 agents/codex/inbox/2026-08-20-readme-release-status.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b8996c1..0805fd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,198 @@ Versions follow the tags in this repository. ## [Unreleased] +### Added +- Link management and a real-time Event Journal in the Control web console (#63) + +### Changed +- Task, report, and acceptance workflow for agents moved into `agents/` (#64) +- `actions/download-artifact` pinned to v8.0.1 across all workflows (#46) +- `docker/setup-qemu-action` pinned to v4.2.0 (#44) + +--- + +## [v0.1.0-alpha.20] — 2026-08-18 + +Published. Carries the work that `v0.1.0-alpha.19` failed to publish. + +### Added +- Release pipeline now tests the latest published release before cutting a new + one (#62) +- Operator web console for nodes, links, and enrollment code generation (#59) +- Guided unified installer (#58) +- Complete server uninstall mode (#60) +- Testing-only password login for the web console (#61) +- Node enrollment endpoint (#53) +- Desktop update proof (#55) + +### Fixed +- Mesh state directory permissions created before Control starts (#57) +- `DEFAULT_RELEASE_TAG` in the packaged convenience installer matches the tag + being produced — the defect that burned `v0.1.0-alpha.19` + +--- + +## [v0.1.0-alpha.19] — 2026-08-18 — burned, not published + +The tag exists, but the Release pipeline failed before a GitHub Release was +published: the packaged convenience installer's `DEFAULT_RELEASE_TAG` did not +match the immutable tag. The version number is burned and must not be moved, +deleted, recreated, or reused. Its content was published under +`v0.1.0-alpha.20`. + +--- + +## [v0.1.0-alpha.18] — 2026-08-18 + +### Fixed +- Wrong-identity negative test selects cosign v3 explicit detached-output mode, + matching the production consumer's detached signature and certificate + contract (#56) + +First release required to complete both automatic `workflow_run` verification +and manual `workflow_dispatch` re-verification. + +--- + +## [v0.1.0-alpha.17] — 2026-08-18 + +### Fixed +- Checksum verification stays fail-closed while its success line is suppressed, + so pass-through commands such as `node-code` return only machine-readable + bootstrap output (#54) + +Automatic verification completed clean-host Hub and Node installation, then the +negative-test harness stopped while creating a wrong-identity signature: +cosign v3 requires an explicit bundle or legacy detached-output mode. + +--- + +## [v0.1.0-alpha.16] — 2026-08-17 + +### Fixed +- Acceptance shell clears its command hash after removing test-provisioned + cosign (#52) + +Automatic verification proved clean-host Hub installation, then failed on the +Node: the convenience installer wrote the checksum success line to stdout ahead +of the machine-readable `SMMNODE2` enrollment code, so the value was rejected. + +--- + +## [v0.1.0-alpha.15] — 2026-08-17 + +### Added +- Pinned, checksum-verified cosign binary provisioned by the installer (#43) + +First release that provisions cosign. Its verification proved clean-host Hub +installation and manifest verification, then stopped before the clean-host Node +installation: the acceptance script retained the deliberately removed cosign +path in Bash's command hash. + +--- + +## [v0.1.0-alpha.14] — 2026-08-15 + +### Fixed +- Release signing consistency between producer and consumer (#41, #42) + +First release with the complete manifest, keyless signature, and Fulcio +certificate set, so its published assets can be verified. A clean host cannot +install it because the release does not provision cosign — preserve it for +verification and historical evidence, do not use it for installation. + +--- + +## [v0.1.0-alpha.13] — 2026-08-13 + +### Fixed +- Windows checksum asset normalized to LF so GNU `sha256sum -c` can consume it + (#39) + +Published with a keyless manifest signature but without the Fulcio signing +certificate required by production consumers. The immutable release remains +published as historical evidence. + +--- + +## [v0.1.0-alpha.12] — 2026-08-13 + +### Fixed +- Network-dependent alpha.8 compatibility test replaced in release + verification (#38) + +Published with a keyless manifest signature but without the Fulcio signing +certificate, so consumers cannot verify that signature. Its Windows +`SHA256SUMS` asset also used CRLF and was not consumable by GNU +`sha256sum -c`. Neither defect is repaired in place. + +--- + +## [v0.1.0-alpha.11] — 2026-08-12 — burned, not published + +The tag exists, but the Release pipeline failed before a GitHub Release was +published. The version number is burned and must not be moved, deleted, +recreated, or reused. + +Content carried by the tag: release contract updated to alpha.10, backward +compatibility test removed from the bootstrap job, Debian VM reboot constraint +documented, translations and roadmap synchronized. + +--- + +## [v0.1.0-alpha.10] — 2026-08-11 — burned, not published + +The tag exists, but the Release pipeline failed before a GitHub Release was +published. The version number is burned and must not be moved, deleted, +recreated, or reused. + +Content carried by the tag: signed delivery queue B (#35), version comparison +fix (#36). + +--- + +## [v0.1.0-alpha.9] — 2026-08-10 + +### Added +- Monitor snapshot contract (#32) + +### Changed +- Single-writer release pipeline: `linux-release.yml` is the sole GitHub + Release publisher (#33) + +`smm-setup.sh`, its checksum, the bootstrap script, platform archives, SBOMs, +and the signed manifest are reproducible from the tagged tree. The installer +fetches only same-tag assets and verifies the bootstrap checksum before +execution. + +--- + +## [v0.1.0-alpha.8] — 2026-08-10 + +### Added +- Source-scoped monitor role (#29) +- Certificate lifecycle management +- Signed delivery, queue A +- Reproducible builds (#15) +- Product horizons and KAgent integration specifications (#13) + +### Fixed +- CycloneDX SBOM generation in release jobs (#28) +- Repository hygiene (#14) + +Contains the v1 `server-monitor-manager-bootstrap-manifest.json` layout and an +orphaned `server-monitor-manager-manifest.sig` without the corresponding +manifest v2. Published assets remain immutable; the anomaly is documented +rather than repaired in place. + +--- + +## [v0.1.0-alpha.7] — 2026-08-09 + ### Added - Background link reconciliation service for the Control plane (#12) +- Link reconciliation driven by factual state (#16) +- Provisioning helper coverage for a missing node row (#17) ### Changed - Link policy reconciliation now runs continuously (#11) @@ -90,7 +280,21 @@ Versions follow the tags in this repository. - Secure node enrollment documentation - Windows build verification in CI -[Unreleased]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.6...HEAD +[Unreleased]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.20...HEAD +[v0.1.0-alpha.20]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.19...v0.1.0-alpha.20 +[v0.1.0-alpha.19]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.18...v0.1.0-alpha.19 +[v0.1.0-alpha.18]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.17...v0.1.0-alpha.18 +[v0.1.0-alpha.17]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.16...v0.1.0-alpha.17 +[v0.1.0-alpha.16]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.15...v0.1.0-alpha.16 +[v0.1.0-alpha.15]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.14...v0.1.0-alpha.15 +[v0.1.0-alpha.14]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.13...v0.1.0-alpha.14 +[v0.1.0-alpha.13]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.12...v0.1.0-alpha.13 +[v0.1.0-alpha.12]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.11...v0.1.0-alpha.12 +[v0.1.0-alpha.11]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.10...v0.1.0-alpha.11 +[v0.1.0-alpha.10]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.9...v0.1.0-alpha.10 +[v0.1.0-alpha.9]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.8...v0.1.0-alpha.9 +[v0.1.0-alpha.8]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.7...v0.1.0-alpha.8 +[v0.1.0-alpha.7]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.6...v0.1.0-alpha.7 [v0.1.0-alpha.6]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.5...v0.1.0-alpha.6 [v0.1.0-alpha.5]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.4...v0.1.0-alpha.5 [v0.1.0-alpha.4]: https://github.com/ochenstarik-ui/server-monitor-manager/compare/v0.1.0-alpha.3...v0.1.0-alpha.4 diff --git a/agents/claude/done/2026-08-20-docs-sync.md b/agents/claude/done/2026-08-20-docs-sync.md new file mode 100644 index 0000000..24af72b --- /dev/null +++ b/agents/claude/done/2026-08-20-docs-sync.md @@ -0,0 +1,87 @@ +# Отчёт: документация приведена в соответствие с историей релизов + +- **Задание:** `../inbox/2026-08-20-docs-sync.md` +- **Агент:** `claude` +- **Дата:** 2026-08-20 +- **Ветка:** `claude/deps-update` + +## Что сделано + +**`CHANGELOG.md`.** Дописаны 14 отсутствовавших версий, alpha.7 … alpha.20. +Записи выведены из тегов и коммитов между ними, а не из памяти. Прежняя +секция `Unreleased` со ссылками на #10–#12 оказалась содержимым alpha.7 — +перенесена туда. Новый `Unreleased` описывает слитое после alpha.20: #63, +#64, #44, #46. Ссылки сравнения версий перестроены для всех 20 тегов. + +Сожжённые номера помечены прямо в заголовке — `burned, not published` — с +указанием, чем упал пайплайн и под какой версией вышло их содержимое: + +- alpha.10 и alpha.11 — пайплайн упал до публикации; +- alpha.19 — `DEFAULT_RELEASE_TAG` в упакованном установщике не совпал + с тегом; содержимое вышло под alpha.20. + +Для опубликованных, но дефектных версий записи содержат сам дефект: +alpha.8 (осиротевшая подпись без manifest v2), alpha.12 и alpha.13 +(подпись без сертификата Fulcio), alpha.14 (проверяемая, но не +устанавливаемая на чистый хост), alpha.15 … alpha.17 (на чём остановилась +проверка). Иначе CHANGELOG подсказывал бы ставить версию, которая не +ставится. + +**`docs/release-policy.md`.** Добавлена запись про alpha.20 — что он +исправляет, что переносит из сожжённого alpha.19. + +**`docs/roadmap.md`.** Веб-консоли в плане не было вовсе, поэтому это не +переключение галочек, а дописывание фактически поставленного. В этап 2: +консоль оператора, отдача ассетов из встроенных ресурсов, вход по паролю +для тестовых стендов. В этап 3: управление Links из консоли, аварийное +отключение, раздельные желаемое/фактическое состояния, журнал событий. +В этап 7: режим полного удаления сервера, пошаговый объединённый установщик. + +## Как проверено + +Все 20 версий на месте: + +``` +$ grep -c "^## \[v0.1.0-alpha" CHANGELOG.md +20 +``` + +Даты записей сверены с датами тегов — расхождений нет: + +``` +$ for n in $(seq 1 20); do t="v0.1.0-alpha.$n"; ... done +v0.1.0-alpha.1 2026-07-16 2026-07-16 совпадает +... +v0.1.0-alpha.20 2026-08-18 2026-08-18 совпадает +``` + +Двадцать строк, все «совпадает». + +## Что не сделано + +**README и одиннадцать переводов не тронуты намеренно.** `README.md:101` +по-прежнему называет `v0.1.0-alpha.14`. `docs/release-policy.md` отдаёт +строку статуса релиза в корневом README и в переводах в единоличное +владение владельцу релиза и прямо требует запрашивать изменение, а не +править самому. Запрошено заданием +`agents/codex/inbox/2026-08-20-readme-release-status.md`. + +Порядок регламента нарушен: задание в `inbox/` записано после выполнения +работы, а не до. Указываю прямо, чтобы это не выглядело соблюдённым. + +## Замечено рядом + +1. **`README.md:101` и переводы** — предмет выданного задания Codex. +2. **В roadmap этап 6 содержит пункт «синхронизировать все переводы README + с текущим release status»** — он остаётся невыполненным и закрывается + тем же заданием. +3. **Содержание записей CHANGELOG выведено из заголовков коммитов и + merge-коммитов.** Там, где заголовок был неинформативен, запись вышла + короче фактического объёма работы. Это не выдумка, но и не полный + пересказ: восстановление постфактум точнее заголовков быть не может. + +## Вопросы к приёмке + +Записи alpha.10, alpha.11 и alpha.19 оставлены в CHANGELOG как сожжённые. +Альтернатива — не упоминать их вовсе. Считаю упоминание правильным: +читатель, увидев разрыв в нумерации, иначе решит, что запись потеряна. diff --git a/agents/claude/inbox/2026-08-20-docs-sync.md b/agents/claude/inbox/2026-08-20-docs-sync.md new file mode 100644 index 0000000..af98c04 --- /dev/null +++ b/agents/claude/inbox/2026-08-20-docs-sync.md @@ -0,0 +1,41 @@ +# Привести документацию в соответствие с фактическим состоянием релизов + +- **Кому:** `claude` +- **Дата:** 2026-08-20 +- **От кого:** владелец проекта (в чате: «делай что можно. и продолжай») +- **Ветка:** `claude/deps-update` +- **Файл отчёта:** `../done/2026-08-20-docs-sync.md` + +## Что нужно сделать + +`CHANGELOG.md` заканчивался на `v0.1.0-alpha.6` от 2026-07-31, тогда как +теги идут до `v0.1.0-alpha.20`. Секция `Unreleased` ссылалась на давно +слитые #10–#12. `docs/release-policy.md` вёл построчную историю версий, но +обрывался на alpha.19. `docs/roadmap.md` не отражал подсистемы, слитые в +`main`. + +Восстановить историю по фактам репозитория — тегам и коммитам между ними, +а не по памяти: + +- CHANGELOG: записи для alpha.7 … alpha.20, сожжённые номера помечены как + сожжённые, ссылки сравнения версий выправлены; +- release-policy: запись про alpha.20; +- roadmap: отметить фактически поставленное. + +## Границы + +Не менять код, workflow и версии сборки. **Не трогать строку статуса релиза +в README и переводах**: по `docs/release-policy.md` эти пути принадлежат +владельцу релиза, изменение запрашивается заданием, а не правится напрямую. + +## Как проверить результат + +- в CHANGELOG присутствуют все 20 версий: `grep -c "^## \[v0.1.0-alpha"`; +- даты записей совпадают с датами тегов: `git log -1 --format=%ad --date=short <тег>`; +- содержание записей выводится из `git log` между соседними тегами. + +## Контекст и ограничения + +Сожжённые номера `alpha.10`, `alpha.11`, `alpha.19` не переиспользуются: +теги существуют, релизы не опубликованы. Запись о них в CHANGELOG обязана +показывать это прямо, иначе читатель решит, что релиз был. diff --git a/agents/codex/inbox/2026-08-20-readme-release-status.md b/agents/codex/inbox/2026-08-20-readme-release-status.md new file mode 100644 index 0000000..90c1639 --- /dev/null +++ b/agents/codex/inbox/2026-08-20-readme-release-status.md @@ -0,0 +1,52 @@ +# Синхронизировать release status в README и переводах + +- **Кому:** `codex` +- **Дата:** 2026-08-20 +- **От кого:** главный агент (`claude`) +- **Ветка:** `codex/readme-release-status` +- **Файл отчёта:** `../done/2026-08-20-readme-release-status.md` + +## Что нужно сделать + +`README.md:101` утверждает, что текущий тестовый выпуск — `v0.1.0-alpha.14`. +Фактически опубликован `v0.1.0-alpha.20`. Те же строки статуса в +одиннадцати переводах `docs/i18n/README.*.md` рассинхронизированы между +собой и с корневым README. + +Привести строку статуса релиза к `v0.1.0-alpha.20` в корневом README и во +всех переводах. + +Задание адресовано тебе, а не выполнено мной, по прямому требованию +`docs/release-policy.md`: владелец релиза имеет единоличное право записи в +version sources, `deploy/**`, `tests/bootstrap/**`, релизные workflow, строку +статуса релиза в корневом README и в переводах. Остальные просят об +изменении в отчёте и не правят эти пути сами. + +Это же закрывает пункт этапа 6 в `docs/roadmap.md`: «синхронизировать все +переводы README с текущим release status». Отметить его выполненным — +часть задания. + +## Границы + +Только строки статуса релиза в README и переводах плюс соответствующий +пункт в `docs/roadmap.md`. Не переписывать остальной текст переводов, не +трогать `CHANGELOG.md` и `docs/release-policy.md` — они уже приведены в +соответствие отдельной работой. Не менять `DEFAULT_RELEASE_TAG` и версии +сборки: релиз этим заданием не выпускается. + +## Как проверить результат + +- `grep -rn "alpha\." README.md docs/i18n/` — ни одной ссылки на версию + ниже `v0.1.0-alpha.20` в строках статуса; вывод команды в отчёт; +- перечислить в отчёте все двенадцать файлов с указанием, какая версия в + каждом стояла до правки. Если где-то стояла не `alpha.14`, а другая — это + само по себе результат, его надо показать; +- `bash tests/bootstrap/test-release-contract.sh` — зелёный, если он + затрагивает README; +- прогоны CI на PR — ссылками. + +## Контекст и ограничения + +Проверка выполнена мной чтением дерева, а не запуском сборки: на машине +разбора нет .NET SDK. Возможно, какой-то из переводов уже актуален — +я сверял только корневой README и не открывал все одиннадцать файлов. diff --git a/docs/release-policy.md b/docs/release-policy.md index 1e21713..beaf168 100644 --- a/docs/release-policy.md +++ b/docs/release-policy.md @@ -21,5 +21,6 @@ Known release history: - `v0.1.0-alpha.17` keeps checksum verification fail-closed while suppressing its success line, so pass-through commands such as `node-code` return only their machine-readable bootstrap output. Its automatic verification completed the clean-host Hub and Node installation, then the negative-test harness stopped while creating a wrong-identity signature because cosign v3 requires an explicit bundle or legacy detached-output mode. The immutable release and failed harness run remain as evidence; the negative test is corrected in the next version. - `v0.1.0-alpha.18` makes the wrong-identity negative test select cosign v3's explicit detached-output mode, matching the production consumer's detached signature and certificate contract. It is the first release required to complete both automatic `workflow_run` verification and manual `workflow_dispatch` re-verification. - `v0.1.0-alpha.19` exists as a tag, but its Release pipeline failed when the packaged convenience installer's `DEFAULT_RELEASE_TAG` did not match the immutable tag. No GitHub Release was published. The version number is burned and must not be moved, deleted, recreated, or reused. +- `v0.1.0-alpha.20` matches the packaged convenience installer's `DEFAULT_RELEASE_TAG` to the tag being produced, which is the defect that burned `v0.1.0-alpha.19`. It also adds a pipeline step that tests the latest published release before a new one is cut. It carries the content that `v0.1.0-alpha.19` failed to publish: the operator web console, the guided unified installer, the complete uninstall mode, the node enrollment endpoint, and the mesh state permission fix. Every release candidate must pass a branch `workflow_dispatch` run of the Release pipeline before its immutable version tag is created. The release owner has sole write ownership of version sources, `deploy/**`, `tests/bootstrap/**`, release workflows, the root README release status, and translated README release statuses. Other contributors request changes to those paths in their report; they do not edit or bump them directly. One pull request covers one release topic and may merge only after required CI is green. diff --git a/docs/roadmap.md b/docs/roadmap.md index af13129..e3a0f6f 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -46,6 +46,11 @@ - [x] ограниченный offline buffer Agent и downsampling; - [x] idempotency и replay protection; - [x] SQLite schema version, retention и backup/restore Control DB + CA; +- [x] веб-консоль оператора на Control: список узлов, состояние агентов и + выпуск кода регистрации; +- [x] отдача ассетов консоли из встроенных ресурсов сборки, когда каталога + `wwwroot` нет на диске; +- [x] вход по логину и паролю для тестовых стендов, отключённый по умолчанию; - [ ] добавить Desktop UI управления Automation identities и токенами. ## Этап 3 — управляемые Links @@ -62,6 +67,12 @@ - [x] B-2: независимая фоновая и emergency-triggered реконсиляция, агрегированное состояние недоступного Mesh firewall и Desktop banner; - [x] B-3: факт-первичная реконсиляция использует один `link-list`, удаляет orphan/дубликаты (включая `Disabled/Disabled`), разводит `Examined` / `Converged` / `Failed` (M2), ограничивает marker-prompt тремя попытками, добавляет фильтр истории и retention завершённых Links (M4), а также типизированное ожидание активации Mesh Node (M5). Physical acceptance остаётся внешним блокером; - [ ] выполнить физический acceptance Hub + source Node + два destination Node с WireGuard/nftables/reboot. +- [x] управление Links из веб-консоли: создание с подтверждением направления, + обязательной причиной и ключом идемпотентности; +- [x] аварийное отключение Link из строки таблицы консоли; +- [x] раздельное отображение желаемого и фактического состояния Link + с признаком рассогласования и последней ошибкой; +- [x] журнал событий Control в реальном времени в веб-консоли; ## Этап 4 — мониторинг и терминал @@ -101,6 +112,8 @@ - [x] добавить криптографическую подпись compatibility manifest для production release; - [x] проверять Ubuntu 22.04/24.04 и Debian 12/13, `amd64`/`arm64`; - [x] добавить non-interactive install/update/rollback/uninstall; +- [x] добавить режим полного удаления сервера; +- [x] добавить пошаговый объединённый установщик; - [x] устанавливать Control/Agent, restricted helper и systemd units; - [x] локально создавать Agent key/CSR, выполнять mTLS enrollment и не сохранять token; - [x] добавить собственную установку WireGuard Hub/Node и выдачу внутренних адресов; -- 2.45.2 From ddb3f559f2311dc9afcdd6b70af8fcea2e372d0e Mon Sep 17 00:00:00 2001 From: Ochenstarik Date: Thu, 20 Aug 2026 16:47:48 +0700 Subject: [PATCH 6/8] =?UTF-8?q?chore(agents):=20=D0=B7=D0=B0=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=20Windows-=D0=BA=D0=BB=D0=B8?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D1=83=20=D0=B8=20=D0=B2=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=BE=D0=BC=D1=83=20=D0=BF=D0=BE=D1=82=D1=80=D0=B5=D0=B1=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8E=20cosign?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Версия MSIX не менялась с 2026-07-31: Package.appxmanifest объявляет 1.0.0.6 во всех четырнадцати релизах после alpha.6, тогда как Windows различает пакеты по версии манифеста. UpdateService при этом сравнивает версию манифеста с именем тега, а не с версией пакета. В задание по cosign добавлен второй потребитель: Windows-обновлятор закрепляет cosign v2.4.0, тогда как Linux-установщик — v3.1.3. Подпись одного релиза проверяется двумя разными версиями, а Release Verification покрывает только Linux-путь. Co-Authored-By: Claude Opus 5 --- .../2026-08-19-cosign-installer-rehearsal.md | 24 +++++-- .../inbox/2026-08-20-msix-version-stuck.md | 63 +++++++++++++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 agents/codex/inbox/2026-08-20-msix-version-stuck.md diff --git a/agents/codex/inbox/2026-08-19-cosign-installer-rehearsal.md b/agents/codex/inbox/2026-08-19-cosign-installer-rehearsal.md index 3e7a9cb..f1fa3fd 100644 --- a/agents/codex/inbox/2026-08-19-cosign-installer-rehearsal.md +++ b/agents/codex/inbox/2026-08-19-cosign-installer-rehearsal.md @@ -20,10 +20,23 @@ В workflow версия cosign не закреплена (`cosign-release` не задан), так что она определяется installer'ом. Сейчас это не определено. 2. **Совместим ли формат подписи, которую произведёт этот cosign, с - потребителем.** `deploy/ochenstarik-server-monitor-manager.sh:34` - закрепляет `COSIGN_VERSION="v3.1.3"` с проверкой SHA-256 и проверяет - подпись через `cosign verify-blob` с отдельным сертификатом Fulcio. - Producer и consumer должны сойтись по формату. + потребителями — обоими.** Потребителей два, и они на разных версиях + cosign: + + - **Linux.** `deploy/ochenstarik-server-monitor-manager.sh:34` закрепляет + `COSIGN_VERSION="v3.1.3"` с проверкой SHA-256 и проверяет подпись через + `cosign verify-blob` с отдельным сертификатом Fulcio. + - **Windows.** `src/ServerMonitorManager.Desktop/UpdateService.cs:79` + закрепляет `CosignVersion = "v2.4.0"` с закреплённым SHA-256 + (`ProcessSignatureVerifier`), скачивает `cosign-windows-amd64.exe` и + выполняет тот же `verify-blob --certificate … --certificate-identity-regexp + …@refs/tags/v.*`. + + То есть подпись одного релиза проверяется cosign v3.1.3 на Linux и cosign + v2.4.0 на Windows. Смена версии у producer должна оставить проверяемым + **оба** пути, а не только тот, который гоняет Release Verification. + Разъезд producer и consumer по cosign — ровно то, на чём проект уже + потерял alpha.12, alpha.13, alpha.17 и alpha.18. 3. **Проходит ли полный релизный путь.** Прогнать `Release pipeline` на репетиционном теге и предъявить, что подпись произведена, а `Release Verification` её проверила на чистом хосте. @@ -43,6 +56,9 @@ cosign-installer тегом вместо SHA уже числится отдел - ссылки на прогоны `Release pipeline` и `Release Verification` с репетиционным тегом и их фактический итог; +- **отдельно — проверка подписи потребителем на cosign v2.4.0**, как это + делает Windows-обновлятор. Release Verification гоняет только Linux-путь, + поэтому Windows-потребитель ею не покрыт; - вывод шага, который печатает версию установленного cosign; - вывод проверки подписи потребителем. diff --git a/agents/codex/inbox/2026-08-20-msix-version-stuck.md b/agents/codex/inbox/2026-08-20-msix-version-stuck.md new file mode 100644 index 0000000..c75ccea --- /dev/null +++ b/agents/codex/inbox/2026-08-20-msix-version-stuck.md @@ -0,0 +1,63 @@ +# Версия MSIX не менялась 14 релизов подряд + +- **Кому:** `codex` +- **Дата:** 2026-08-20 +- **От кого:** главный агент (`claude`) +- **Ветка:** `codex/msix-version` +- **Файл отчёта:** `../done/2026-08-20-msix-version-stuck.md` + +## Что нужно сделать + +`src/ServerMonitorManager.Desktop/Package.appxmanifest:13` содержит +`Version="1.0.0.6"`. Последний раз её меняли 2026-07-31 коммитом `c320b7d` +«chore(release): bump MSIX version to 1.0.0.6 (#9)» — то есть под +`v0.1.0-alpha.6`. С тех пор выпущено четырнадцать версий, вплоть до +`v0.1.0-alpha.20`, и в каждой из них MSIX объявляет себя как `1.0.0.6`. + +Windows различает пакеты по версии в манифесте, а не по имени файла и не по +тегу GitHub. Установка нового MSIX поверх уже установленного с той же +версией не считается обновлением. + +Нужно: + +1. Определить фактическое поведение: устанавливается ли MSIX из alpha.20 + поверх установленного MSIX из alpha.14, и что именно происходит. + Пока это **не определено** — я проверял чтением дерева, не установкой. +2. Если обновление действительно не проходит — связать версию пакета с + версией релиза, чтобы она поднималась при каждом выпуске автоматически, + а не руками. +3. Учесть, что `UpdateService` сравнивает версию манифеста с именем тега + релиза (`UpdateService.cs:256–262`), а не с версией пакета. Значит + обновлятор может считать обновление доступным и скачать MSIX, который + Windows затем откажется ставить. Проверить эту связку целиком. + +## Границы + +`Package.appxmanifest`, скрипты сборки Windows-установщика +(`build/windows/**`) и, если потребуется, `windows-release.yml`. Не менять +логику `UpdateService` без отдельного основания: сначала измерение, потом +правка. Не трогать `src/**` вне Desktop, консоль и Linux-часть. + +## Как проверить результат + +- вывод `Get-AppxPackage` до и после установки: версия должна отличаться; +- показать установку MSIX новой версии поверх предыдущей на машине, где + предыдущая уже стоит, и её фактический результат; +- если решение автоматизирует поднятие версии — показать два прогона сборки + с разными тегами и разные версии в получившихся манифестах. + +«Версия теперь поднимается» без установки поверх предыдущей результатом +проверки не является: проблема ровно в установке. + +## Контекст и ограничения + +Дефект найден чтением дерева и истории git, установка не выполнялась: на +машине разбора нет ни .NET SDK, ни установленного пакета. Если при проверке +окажется, что Windows нормально ставит MSIX той же версии поверх себя, — +так и напиши с выводом команд; это допустимый результат. + +MSIX подписан тестовым сертификатом (`Publisher="CN=AppPublisher"`, +ассет `ServerMonitorManager-test-signing.cer`), поэтому для установки нужен +импорт этого сертификата в доверенные корневые. Постоянная доверенная +Windows code-signing identity в `docs/roadmap.md` числится невыполненной +(этап 6). Это отдельная задача, здесь её решать не нужно. -- 2.45.2 From 3960d30ee63d4593925bd80d7039e2774dfe11e2 Mon Sep 17 00:00:00 2001 From: Ochenstarik Date: Thu, 20 Aug 2026 17:34:45 +0700 Subject: [PATCH 7/8] =?UTF-8?q?chore(agents):=20=D0=B7=D0=B0=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=2030-=D1=81=D0=B5=D0=BA=D1=83?= =?UTF-8?q?=D0=BD=D0=B4=D0=BD=D0=BE=D0=BC=D1=83=20=D0=BE=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=81=D1=83=20=D1=81=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8F=20Links?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Служба тикает с периодом min(LinkReconciliationSeconds, 30) и на каждом тике безусловно запускает sudo с helper'ом для инспекции маркера. Настройка ограничивает только полный проход, поэтому при 3600 получается около 120 привилегированных запусков в час. Проверка backoff стоит после обращения к маркеру, так что при недоступном firewall вызовы продолжаются. Измерено на локальном прогоне: записи ровно каждые 30 секунд при заданных 3600, при нуле узлов и нуле связей. Co-Authored-By: Claude Opus 5 --- ...2026-08-20-reconciliation-poll-interval.md | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 agents/antigravity/inbox/2026-08-20-reconciliation-poll-interval.md diff --git a/agents/antigravity/inbox/2026-08-20-reconciliation-poll-interval.md b/agents/antigravity/inbox/2026-08-20-reconciliation-poll-interval.md new file mode 100644 index 0000000..d941275 --- /dev/null +++ b/agents/antigravity/inbox/2026-08-20-reconciliation-poll-interval.md @@ -0,0 +1,101 @@ +# Согласование Links дёргает привилегированный процесс каждые 30 секунд + +- **Кому:** `antigravity` +- **Дата:** 2026-08-20 +- **От кого:** главный агент (`claude`) +- **Ветка:** `antigravity/reconciliation-poll-interval` +- **Файл отчёта:** `../done/2026-08-20-reconciliation-poll-interval.md` + +## Что происходит + +`LinkReconciliationBackgroundService` тикает с периодом +`Math.Min(LinkReconciliationSeconds, 30)` (строка 117), то есть **не реже +раза в 30 секунд при любой настройке**. На каждом тике первым делом +безусловно вызывается `applier.GetReconciliationRequestAsync(...)` +(строка 30) — а это запуск внешнего процесса +`/usr/bin/sudo` + `ochenstarik-smm-policy-apply` +(`LinkPolicyApplier.RunAsync`, строка 143). + +Отсюда два следствия. + +**1. Настройка не ограничивает привилегированные вызовы.** +`LinkReconciliationSeconds` валидируется в диапазоне 30…3600, и оператор, +поставивший 3600, вправе ожидать примерно одну активность в час. Фактически +он получает около **120 запусков sudo в час** — интервал управляет только +полным проходом `ReconcileAllAsync`, но не инспекцией маркера. + +**2. Backoff не подавляет эти вызовы.** Проверка `_backoffUntil` +(строки 35–38) стоит **после** обращения к маркеру. Когда firewall +недоступен и служба ушла в backoff, она всё равно продолжает запускать +sudo каждые 30 секунд — ровно в той ситуации, когда предполагалось +притормозить. + +Каждая неудачная инспекция пишет предупреждение с полным стеком. + +## Измерение + +Control запущен локально с `--Control:LinkReconciliationSeconds=3600`. +Журнал приложений Windows, провайдер `.NET Runtime`, категория +`ServerMonitorManager.Control.LinkReconciliationBackgroundService`: + +``` +17:29:16 +17:29:46 +17:30:16 +17:30:46 +17:31:16 +``` + +Ровно каждые 30 секунд при заданных 3600. Записи идут непрерывно, службы +в этот момент нечем было заниматься: узлов ноль, связей ноль. + +## Что нужно сделать + +Привести поведение в соответствие с настройкой, **не потеряв быструю +реакцию на маркер** — она и есть смысл 30-секундного опроса, её ломать +нельзя. + +Как минимум: + +1. Не обращаться к маркеру, пока действует `_backoffUntil`. Сейчас backoff + не защищает ни от чего. +2. Решить и обосновать в отчёте, каким должен быть контракт + `LinkReconciliationSeconds`. Либо это интервал полного прохода, и тогда + частота опроса маркера должна настраиваться отдельным параметром с + собственной валидацией и описанием. Либо это верхняя граница любой + активности, и тогда опрос обязан её соблюдать. +3. Сделать так, чтобы повторяющаяся недоступность helper'а не писала + полный стек на каждом тике. + +Выбор между вариантами пункта 2 — за тобой, но он должен быть **выбором с +обоснованием**, а не молчаливым изменением поведения. + +## Границы + +`src/ServerMonitorManager.Control/LinkReconciliationBackgroundService.cs`, +при необходимости `ControlOptions` и валидация в `Program.cs`, плюс тесты +`tests/ServerMonitorManager.Control.Tests/LinkReconciliationTests.cs`. +Не трогать `LinkService.ReconcileAllAsync`, helper в `deploy/**`, консоль +и Desktop. + +## Как проверить результат + +- `dotnet test tests/ServerMonitorManager.Control.Tests/...` — все 158 + существующих тестов зелёные, с выводом. Маркерные тесты трогать только + если меняется контракт, и тогда объяснить каждое изменение; +- новый тест на то, что во время backoff обращения к маркеру **не + происходит**: подменить `ILinkPolicyApplier` и сосчитать вызовы; +- новый тест на соблюдение настроенного интервала по выбранному контракту; +- предъявить число вызовов applier за фиксированное время до и после + правки — как в измерении выше, числами. + +## Контекст и ограничения + +Дефект найден на живом прогоне Control на Windows, где helper'а нет вовсе, +поэтому каждая инспекция падает. На настоящем Hub helper есть и вызовы +успешны — значит там это не ошибки в журнале, а тихая нагрузка: запуск +sudo и внешнего процесса дважды в минуту круглосуточно. Оценить, насколько +это существенно на настоящем Hub, я не могу: живого Hub под рукой нет. +Если при проверке окажется, что нагрузка пренебрежима и контракт менять не +нужно, — так и напиши с числами, это допустимый результат. Пункт 1 про +backoff при этом всё равно остаётся к исправлению. -- 2.45.2 From 7fac6d5d222ea72731244b5c4945ca085698ffad Mon Sep 17 00:00:00 2001 From: Ochenstarik Date: Thu, 20 Aug 2026 17:38:52 +0700 Subject: [PATCH 8/8] =?UTF-8?q?chore(agents):=20=D0=B7=D0=B0=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20Antigravity=20=D0=BF=D0=BE=20=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D1=80=D0=B8=D0=BA=D0=B0=D0=BC=20=D1=83=D0=B7=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B2=20=D0=BA=D0=BE=D0=BD=D1=81=D0=BE=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows-клиент показывает CPU, память, диск, задержку и здоровье по каждому серверу, веб-консоль не показывает ничего из этого. Данные при этом уже лежат на Hub: таблица metric_samples наполняется из heartbeat и чистится по MetricRetentionHours, но в группе /api/v1/control нет ни одного маршрута для их чтения. Границей задания зафиксировано то, что переносить нельзя: SSH-терминал и приватные ключи остаются на Windows-машине, это заявленное свойство продукта, а не объём работы. Co-Authored-By: Claude Opus 5 --- .../inbox/2026-08-20-console-node-metrics.md | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 agents/antigravity/inbox/2026-08-20-console-node-metrics.md diff --git a/agents/antigravity/inbox/2026-08-20-console-node-metrics.md b/agents/antigravity/inbox/2026-08-20-console-node-metrics.md new file mode 100644 index 0000000..091c1de --- /dev/null +++ b/agents/antigravity/inbox/2026-08-20-console-node-metrics.md @@ -0,0 +1,110 @@ +# Метрики и короткая история узлов в веб-консоли + +- **Кому:** `antigravity` +- **Дата:** 2026-08-20 +- **От кого:** главный агент (`claude`), по задаче владельца «консоль надо + сделать так же, как и Windows-программа» +- **Ветка:** `antigravity/console-node-metrics` +- **Файл отчёта:** `../done/2026-08-20-console-node-metrics.md` + +## Зачем + +Windows-клиент на странице «Серверы» показывает по каждому серверу CPU, +память, диск, задержку, состояние здоровья и статус +(`Pages/ServersPage.xaml`: `CpuText`, `MemoryText`, `DiskText`, +`LatencyText`, `HealthText`, `Status`). Веб-консоль не показывает ничего из +этого: в ней есть только имя узла, состояние, версия агента, время +heartbeat и остаток срока сертификата. + +Это первая из нескольких задач по сближению консоли с Windows-клиентом. +Здесь закрывается ровно метрики и короткая история — остальное перечислено +ниже и в эту задачу не входит. + +## Установленный факт, от которого отталкиваемся + +Данные **уже есть на Hub**, показывать нечем. + +`ControlStore` содержит таблицу (`ControlStore.cs:81`): + +```sql +CREATE TABLE IF NOT EXISTS metric_samples ( + sequence INTEGER PRIMARY KEY AUTOINCREMENT, + node_id TEXT NOT NULL REFERENCES agents(node_id) ON DELETE CASCADE, + recorded_at TEXT NOT NULL, + payload_json TEXT NOT NULL +); +CREATE INDEX IF NOT EXISTS ix_metric_samples_node_time + ON metric_samples(node_id, recorded_at DESC); +``` + +Наполняется она из heartbeat агента, чистится по `MetricRetentionHours` +(по умолчанию 168 часов). При этом в группе `/api/v1/control` **нет ни +одного маршрута для метрик** — я перечитал все `control.Map*` в +`Program.cs`. То есть оператор физически не может их получить. + +## Что нужно сделать + +1. **Добавить в Control чтение метрик под ролью Operator.** Как минимум + последний срез по каждому узлу и история по одному узлу за period. + Форму запроса, имена полей и ограничение на объём выбираешь сам и + обосновываешь в отчёте. Обязательные требования: маршрут в группе + `control` (то есть `RequireAuthorization("Operator")`), ограничение + количества возвращаемых точек, и никакого доступа к чужим данным по + роли Agent или Automation. +2. **Показать это в консоли** в разделе узлов: текущие CPU, память, диск и + задержка рядом с узлом, плюс короткая история — так же, как её + показывает Windows-клиент. +3. **`payload_json` — данные из внешнего источника.** Он приходит от + агента. Разбирать его в консоли только через уже имеющийся + `escapeHtml`, как это сделано с payload событий; ни одной вставки в + `innerHTML` без экранирования. Отсутствующие или битые поля не должны + ронять таблицу узлов. + +## Границы — что переносить нельзя + +**SSH-терминал и приватные ключи в веб-консоль не переносятся.** Это не +вопрос трудоёмкости, а заявленное свойство продукта: README обещает +«opens direct SSH terminals without sending a private terminal key to the +Hub», а ключ мониторинга и сертификат оператора защищены DPAPI и лежат +только на Windows-машине. Страница Sessions остаётся у Windows-клиента. + +Также не входит в эту задачу и делается отдельно: страница Settings, +группы и теги серверов, alert rules и журнал уведомлений (последние два +пункта в `docs/roadmap.md` числятся невыполненными и для Windows-клиента). + +Не трогать: `deploy/**`, релизные workflow, Desktop, схему существующих +таблиц (добавление индексов допустимо и обосновывается). + +## Как проверить результат + +- новый маршрут закрыт ролью: запрос без токена → 401, под ролью Agent и + Automation → 403, под Operator → 200. Три теста, вывод в отчёт; +- ограничение объёма истории проверено тестом: запрос заведомо большего + количества точек возвращает не больше предела; +- битый или неполный `payload_json` не роняет ни маршрут, ни отрисовку — + тест на каждую сторону; +- `dotnet test` целиком зелёный, с выводом; +- прогоны CI на PR — ссылками. + +## Связь с другими заданиями + +Эта задача пересекается с двумя уже выданными и делать её нужно **после** +них, иначе правки лягут друг на друга в одном файле: + +- `2026-08-19-console-behaviour-tests.md` — поведенческие тесты консоли. + Новая функциональность обязана прийти с такими тестами сразу, а не + проверками строк в HTML; +- `2026-08-19-console-events-throttle.md` — троттлинг обновления дашборда. + Метрики увеличат объём каждого обновления, поэтому без троттлинга + усиление нагрузки станет заметнее. + +Если считаешь, что порядок должен быть другим, — скажи в отчёте и обоснуй, +это решение приму. + +## Контекст и ограничения + +Проверено чтением кода и запуском Control локально на пустой базе: узлов +ноль, метрик ноль. Как выглядят настоящие `payload_json` от живого агента, +я не видел — на живом Hub не проверял. Прежде чем фиксировать контракт +ответа, посмотри фактическую форму payload в коде агента, а не в моём +описании. -- 2.45.2