server-monitor-manager/agents/_accepted/2026-08-19-console-links/review-by-claude.md
Ochenstarik 771c252e79 chore(agents): приёмка PR #63 и задание Codex по cosign
Пара «задание — разбор» по PR #63 перенесена в agents/_accepted/ с
основанием приёмки и перечнем того, чего приёмка не доказывает: тесты
главным агентом не запускались, на машине приёмки нет .NET SDK.

Задание Codex требует определить версию cosign у installer 4.1.2, сойтись
с потребителем по формату подписи и предъявить прогон релизного пути с
перечнем шагов, пропущенных при репетиции.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 00:11:33 +07:00

116 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Отчёт: разбор 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-*`-атрибуты
(347351). Непроэкранированных вставок пользовательских данных не найдено.
- **Разбор NDJSON корректен.** app.js:412413 — `split('\n')` с
возвратом хвоста в буфер через `pop()`; разрыв события на границе чанка
не теряется и не портит разбор.
- **Переподключение не размножается.** `startEventStream` вызывается ровно
из двух мест (app.js:89 при инициализации и 431 по таймеру), в начале
функции прежний `AbortController` прерывается. Накопления параллельных
таймеров нет.
- **Журнал ограничен**: `MAX_EVENTS_IN_JOURNAL = 100`, `unshift` + `pop`
(app.js:437439). Неограниченного роста в долгоживущей вкладке нет.
## Замечания
**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:444448).**
```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:230233). Ни 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.