Пара «задание — разбор» по PR #63 перенесена в agents/_accepted/ с основанием приёмки и перечнем того, чего приёмка не доказывает: тесты главным агентом не запускались, на машине приёмки нет .NET SDK. Задание Codex требует определить версию cosign у installer 4.1.2, сойтись с потребителем по формату подписи и предъявить прогон релизного пути с перечнем шагов, пропущенных при репетиции. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
116 lines
7.4 KiB
Markdown
116 lines
7.4 KiB
Markdown
# Отчёт: разбор 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.
|