ADR 0168 — Golden-set QA начинает работать в CI, по расписанию и еженедельно
Статус
Accepted. Частота была решена сопровождающим 2026-09-27 (AT-149): еженедельно. Ссылается на ADR 0123 (golden-set семантического суждения QA, рождённый ручным) и ADR 0138 (образец RAG, который объявил golden-set QA "целиком ручным"). Не редактирует ни один из них.
Контекст
ADR 0123 оставил golden-set QA как TODO(humano) для CI, говоря, что
его включение требует "segredo de LLM de API ou infra nova (GPU)". ADR 0138 повторил
эту фразу, отделяя RAG (embedding, детерминированный) от QA (чат, суждение).
Два измерения изменили картину, и оба есть в
docs/explanation/gates.md:
- AT-067 (2026-09-13): на
ubuntu-latestбез GPU, сqwen2.5-coder, скачанным в Ollama самого job, время укладывается (19–23 минmix golden_set.qa). Половина "новой инфраструктуры" отпала. Но счёт был 0/6 по построению: с RN-502npm testпроектаcontainerбез контейнераrunningотклоняется, а seed никогда не поднимал его. - AT-076 (2026-09-27): seed начал поднимать контейнер продакшен-путём
(
container_startпредложен и одобрен, broker, машина состояний), не трогая RN-502. Два прогона в CI: 3/6 и 3/6 против порога 1/6, 52 и 86 мин job.
Когда инструмент измеряет, не хватало частоты.
Пробный прогон этого workflow (run 36327281774, временный триггер
push, убранный перед PR) снова дал 3/6, по другому набору случаев,
с нулём отказов RN-502, за 13 мин 41 с job — ни один случай в этот раз не повторял
команду до предела. Время колеблется от 14 до 86 мин между прогонами.
Решение
.github/workflows/golden-set-qa.yml, отдельно от ci.yml и от RAG,
еженедельный schedule + workflow_dispatch, никогда pull_request. Тот же
аргумент, что в ADR 0138: ci.yml — только pull_request, а golden-set, который судит
чат-моделью, не стоит на пути merge. Суббота, 01:17 UTC: вне
ежедневного окна RAG (06:00), воскресенья проверок свойств (04:00) и
понедельника проверки ссылок (06:00); суббота — чтобы красное ждало начала
недели; минута 17 — потому что schedule Actions опаздывает и может отбрасывать
запуски в начале часа.
Еженедельно, а не еженощно. RAG стоит ~20 мин и детерминирован:
вчерашняя регрессия — это регрессия. Этот стоит 52–86 мин измеренных и МЕНЯЕТСЯ — два
прогона AT-076 дали одинаковый итог с разными случаями. Один прогон в
день тратил бы часы runner в неделю на чтение того же сигнала тенденции
с большим шумом; один в неделю — то, что нужно порогу (ratchet), чтобы обнаружить
падение, а workflow_dispatch покрывает того, кто менял prompt QA и хочет
ответ сразу.
timeout-minutes: 150. Самый долгий измеренный job занял 86 мин; разброс — от
модели (один случай повторил npm test 30 раз, прежде чем завершить
blocked(modelo)). 150 покрывает прогон, в котором больше одного случая упирается в предел
итераций, не становясь красным по времени, что не является тем, что измеряет job.
Вердикт — вердикт теста. ExUnit проваливается, когда попадания оказываются ниже
passRate из floor.json для модели и когда api отвечает, а seed
падает. Workflow добавляет две защиты инструмента, ни одной —
суждения: строка счёта должна существовать (тест ПРОПУСКАЕТСЯ, когда api не
отвечает, а пропуск в запланированном прогоне — это зелёное, которое не измерило), и в event log
не может быть отказа RN-502 (известная сигнатура AT-067). При сбое
делает то, что делает RAG: печатает журналы. Не открывает issue.
Api, engine и broker нативно на runner, а сокет Docker — только у broker.
Это конструкция, измеренная в AT-076. Одна и та же управляемая папка с трёх сторон, потому
что api и engine работают на хосте (PROJECT_WORKSPACES_ROOT =
PROJECT_WORKSPACES_HOST_ROOT). Образ случаев скачивается до seed, а
ссылка берётся из самого seed (IMAGEM_DO_GOLDEN_SET_QA, закреплённая по digest
индекса), а не из второго литерала в workflow: docker run broker выполняется
под 30-секундным управляющим пределом порта Docker
(RN-604), и расхождение между тем, что скачивает job,
и тем, что просит seed, поместило бы pull внутрь этого предела.
Последствия
TODO(humano) ADR 0123 для CI закрывается. За человеком остаётся то,
что уже говорил сам ADR 0123: порог (floor.json) пишет только человек,
после измерения. Этот ADR его не трогает, как и модель.
Ни один gate не меняется. У golden-set QA нет собственного gate в реестре
(docs/gates.yml); это сигнал тенденции семантического шага
qa-verificada, а запланированный job не блокирует никакого merge.
Broker CI не имеет пяти слоёв compose. На эфемерном runner нет
сети internal и закрытого порта: остающееся сдерживание — то, что broker
ПРИНИМАЕТ (пять операций, spec, вычисляемая api из артефакта).
Runner удаляется в конце job и не хранит никакого секрета этого workflow
(permissions: contents: read, литеральный сервисный токен CI).
Объявлено, здесь не исправлено: heartbeat engine закрывает сессии
seed (heartbeat_timeout) примерно через 30 с после создания, пока QA продолжает
предлагать в них команды (он работает в процессе mix, вне сессии), без
видимого влияния на счёт AT-076. А pull_request, меняющий этот workflow,
его не выполняет — зелёное в PR не доказательство; доказательство — workflow_dispatch или
первая суббота.