ADR 0092 — platform рождается как скрипт отчёта по требованию, а не агент
Статус
Принят. Не меняет ни status: planned, ни gate_saida роли platform
в docs/fluxo.yml (ADR 0085) — её активация по-прежнему синхронизирована с
DEPLOY_ENABLED, которого не существует. Этот документ поставляет лишь ту половину, за которой уже
стоят реальные данные.
Контекст
docs/fluxo.yml (camada_plataforma) описывает platform как "SRE /
Platform — владелец обратной петли": она получала бы pipeline-verde от
области Infra и nfrs-mensuraveis от Arquiteto и возвращала бы
slo + dashboard + runbook, telemetria-consolidada и postmortem.
status — planned, а ativacao записана как "синхронизирована с
DEPLOY_ENABLED" — флагом, которого сегодня в продукте нет. Нет продакшен-
окружения с реальным трафиком, нет численного SLO, определённого где-либо,
и нет реального инцидента, который мог бы проанализировать какой-либо postmortem.
Владелец продукта сознательно решил предвосхитить часть этой роли —
не как LLM-агента и не как супервизируемый процесс (GenServer), которые
выдумали бы полномочия над петлёй, ещё не замыкающейся, а как то, что уже
честно возможно: СКРИПТ чтения, по тому же образцу, что
apps/api/scripts/medir-execucao.ts (FASE 13b) и
apps/api/scripts/validacao-gates.ts (FASE 15).
Данные уже существуют. DomainGaugesCollector
(apps/api/src/infrastructure/observability/domain-gauges.collector.ts)
запускается каждые METRICS_GAUGE_INTERVAL_MS и поддерживает три gauge Prometheus:
активные/закрывающиеся сессии по проекту, заблокированные tasks по проекту и состояние
последней резервной копии (backup_runs — возраст, статус, размер, всегда ГЛОБАЛЬНО,
потому что продукт делает резервную копию всей базы, а не по проекту). Не хватало
не метрики: не хватало способа посмотреть на этот снимок СЕЙЧАС, для конкретного
проекта, не открывая Grafana.
Решение
apps/api/scripts/relatorio-telemetria.ts, вызываемый через
pnpm --filter api relatorio:telemetria [--projeto <uuid>] [--json]. Он
задаёт ТЕ ЖЕ три вопроса, что DomainGaugesCollector, — но как точечное,
разовое чтение, запускаемое тем, кто просит, и завершается после печати. Это не
второй коллектор: он не регистрирует ни одного gauge, не работает в setInterval.
SQL-запросы повторены, а не импортированы. Методы коллектора
(collectSessions/collectBlockedTasks/collectBackup) приватны и
заканчиваются записью в this.metrics.*.set(...) — нет чистой половины
"только запрос", которую можно было бы извлечь, не связывая разовый скрипт с жизненным
циклом @Injectable NestJS, имеющим смысл лишь внутри модуля.
Повторить ЧИТАЮЩИЙ запрос (те же таблицы, те же фильтры) дешевле,
чем открыть эту зависимость.
Отчёт никогда не выдумывает того, чего у него нет. Два фиксированных раздела в каждом выводе:
- "Где посмотреть больше" — ссылки на то, что уже существует, версионировано: три
дашборда в
deploy/k8s/observability/dashboards/*.json, оповещения вdeploy/k8s/observability/alerts/brabo-alerts.yaml,docs/runbook.md#observabilidadeиpnpm dev:obsдля подъёма локальной наблюдаемости. Скрипт ССЫЛАЕТСЯ, никогда не дублирует содержимое этих файлов. - "Не измерено" — три названных пробела: формальный численный SLO (ни один
не определён нигде в продукте — выдумать его здесь было бы той же
ошибкой, которую ADR 0042 уже отвергает для оценки модели, а ADR 0077
отвергает для качества кода); postmortem (зависит от реального
инцидента); телеметрия обратно в продукт в ЗАМКНУТОЙ ПЕТЛЕ (этот скрипт
наблюдает и печатает — не решает и не действует сам; именно это сделало бы
platformactive, а триггер по-прежнему отсутствует).
docs/fluxo.yml получает примечание, а не новый статус. status: planned
роли platform НЕ меняется, как и gate_saida: { id: operavel, status: planned }. Выход telemetria-consolidada получает поле
nota, говорящее, что РУЧНАЯ версия/по требованию уже реальна (этот скрипт), а
АВТОМАТИЧЕСКАЯ версия/замкнутая петля остаётся в ожидании DEPLOY_ENABLED, — та же
дисциплина, которую ADR 0077 уже применил к "рекомендуемой" vs. "выдуманной
оценке": то, что существует, называется существующим, а то, чего нет, по-прежнему
называется несуществующим.
Последствия
Что начинает существовать. Способ ответить "как этот проект
сейчас" (сессии, заблокированные tasks, резервная копия), не открывая Grafana и не
дожидаясь следующего scrape, — полезный именно потому, что DomainGaugesCollector
уже публикует эти данные для Prometheus, но никто не читал их точечно
раньше.
Что остаётся ровно как было. platform остаётся planned.
Ни нового агента, ни GenServer, ни численного SLO, ни
имитированного postmortem. Скрипт ничего не решает и не действует — он лишь печатает
то, что уже есть в базе.
Дублирование запроса — выбор, а не небрежность. Одни и те же
таблицы (sessions, tasks/stories, backup_runs) читаются дважды
двумя разными путями — периодическим коллектором и этим скриптом по
требованию, — и два запроса могут со временем разойтись, если один изменится без
сопровождения другого. Принятая цена меньше, чем цена связывания CLI-скрипта
с жизненным циклом @Injectable NestJS лишь ради повторного использования
приватного кода.
Ссылки
- ADR 0085 — объявляет роль
platformкакplanned; этот документ её не продвигает. - ADR 0042, ADR 0077 — та же дисциплина никогда не выдумывать число/оценку без реальных данных.
- RN-385, RN-386.
apps/api/scripts/relatorio-telemetria.ts,apps/api/src/infrastructure/observability/domain-gauges.collector.ts,docs/fluxo.yml(camada_plataforma › platform).