Перейти к основному содержимому

ADR 0054 — Gates как декларативный реестр

Статус​

Предложен

Контекст​

Gates потока (QA, SecOps, ручное продвижение story, план принятия, ручной merge, конвейер proposed_actions) существуют и были проверены реальным выполнением (ADR 0020, 0044–0046), но они неявные: разбросаны по prompts агентов, коду engine, чистым правилам api и соглашениям CLAUDE.md.

Урок Фазы 10/13 — метрика извлекается скриптом, никогда не записывается вручную — нельзя применить к gate, который нельзя перечислить.

ADR 0048 решил нижнюю половину этой проблемы: поместил решение о действии в event log с реальным актором и заставил proposed_action.created нести status — то, что отличает "пользователь кликнул" от "политика решила сама". Без этого измерение прохождения gate было бы подсчётом несуществующих событий. Этот ADR — верхняя половина: сказать, КАКИЕ gates существуют, чтобы то, что 0048 сделал наблюдаемым, стало и перечислимым.

Решение​

Декларативный реестр в docs/gates.yml, версионируемый, со схемой: id, поток, владелец (агент/область/пользователь), входы, результат, verificacao (script | humana), severidade (block | warn), aprovacao_humana, status (active | planned).

Правила:

  • Gate без скрипта проверки рождается warn; повышение до block требует, чтобы скрипт существовал и измерил прохождения (та же философия, что staged rollout документации).
  • aprovacao_humana: true неизменяем продуктовой конфигурацией в gates, которые конституция объявляет ручными (merge в защищённую, продвижение story в ручном режиме, план принятия, решение о действии), — гарантировано тестом, как ручной merge уже гарантирован.
  • status: planned объявляет gate будущей роли, не активируя его.

evidencia: где живёт доказательство​

Поле, которого исходная spec не предусматривала и которое первое чтение кода сделало обязательным: не у каждого gate может быть доказательство в event log.

  • merge-protegida не выдаёт собственного события. Это предел, применяемый последним поверх уже вычисленного вердикта (decide.ts), который понижает auto_approve до require_approval; исход проявляется как ожидающий proposed_action.created, неотличимый от любой другой ожидающей позиции. Замок гарантирует тест.
  • backmerge живёт полностью вне приложения: это обязательная проверка PR, с состоянием, версионируемым в .release/gate.json на main.

Без этого поля правило "gate active + block без свидетельства в журнале проваливается" сделало бы оба красными навсегда — а они самые жёсткие замки продукта. Поэтому каждый gate объявляет evidencia: event_log | teste | ci вместе с локатором (типы событий и фильтр payload, путь spec или workflow). Скрипт требует event log только от тех, кто его объявляет; для teste и ci он подтверждает, что цель существует.

Альтернатива — понизить оба до warn — отвергнута, потому что лжёт о реальной серьёзности, а покончить именно с этим и существует реестр.

Gates репозитория входят вместе​

backmerge, pr-no-lugar-certo, aprovacoes-da-escada и promocao-conferida (ADR 0030) являются gates по тому же критерию, что и остальные: у них есть владелец, вход, результат, механическая проверка и серьёзность. И именно они чаще всего отклоняют PR в повседневной работе. Включить только backmerge было бы произвольно — это одно и то же семейство (чистый скрипт + workflow + spec).

aprovacoes-da-escada — единственный gate CI с aprovacao_humana: true: то, что он измеряет, — люди, одобряющие по ролям. Реестр gates, опустивший бы именно gate, считающий человеческие подписи, опустил бы самый очевидный.

Предел: реестр — индекс, а не политика. Над ветками по-прежнему властвует docs/explanation/branching-policy.md; entrada и entregavel — одна фраза, а onde указывает на скрипт. YAML никогда не воспроизводит правило — если бы воспроизводил, стал бы вторым источником истины, избегать которого он существует.

Фильтр важен так же, как тип​

qa-verificada и secops-segura — не два типа событий: оба записывают pr.gate_changed, различаемые по payload.gate. И тот же тип записывается при ОТКРЫТИИ gate, без veredito. Реестр, хранящий лишь имя типа, считал бы открытие прохождением и измерял бы вдвое больше случившегося. Поэтому evidencia несёт фильтр payload, а не только тип.

По той же причине суждение о PR инфраструктуры — это два gate (infra-qa-verificada и infra-secops-segura): infra.gate_changed тоже различает по payload.gate, и их объединение сообщало бы прохождение одного так, будто это прохождение другого. Тест утверждает, что ни одна пара (event_types + filtro) не повторяется в реестре, — именно эта уникальность делает измерение осмысленным.

Рассмотренные альтернативы​

  • Оставить неявным в prompts: отвергнуто — неизмеримо.
  • Таблица в базе вместо YAML: пока отвергнуто — gates меняются ревьюируемым PR, а не в runtime; следует прецеденту .docmap.yml и версионируемых rulesets (ADR 0030). Миграция в базу останется тривиальной с loader как границей.

Последствия​

  • Режим community в approval-ladder (backlog) становится изменением значений в aprovacao_humana, а не переписыванием агентов.
  • Dev Lead (ADR 0053) и Platform/SRE получают контракт входа: когда они будут реализованы, их gate уже специфицирован как planned.
  • Реестр рождается, зная о gates, которые исходный список забыл, — суждение QA/SecOps о PR инфраструктуры, у которого собственный путь (infra.gate_changed), потому что за ним нет task backlog. Перечисление находит то, что было вне учёта: это первый дивиденд реестра, ещё до того, как он что-либо измерит.
  • И находит пробел: promocao-conferida — обязательная проверка без собственного spec, в отличие от pr-police и approval-ladder. Её свидетельство указывает на скрипт вместо теста, с записанным там пробелом. Он идёт в триаж 13c как пункт, а не исправляется здесь — фаза объявляет и измеряет, а не чинит.

Ссылки​

  • ADR 0048 — решение в event log, без которого нечего было бы измерять
  • ADR 0020 — gates, проверенные реальным выполнением
  • ADR 0030 — версионируемые rulesets, прецедент конфигурации в файле
  • docs/gates.yml — реестр