Записи об архитектурных решениях¶
Проект может требовать запись об архитектурном решении, когда изменение принимает решение уровня архитектуры. Проверка читает историю Git и не меняет файлы. Она включается явно: без .embraion/decisions.yaml возвращает skipped, а embraion check её не запускает.
Записи лежат в одной папке. Свяжите её со слотом контракта проекта decisions; по умолчанию это docs/architecture/decisions/.
# .embraion/knowledge.yaml
slots:
decisions: docs/architecture/decisions
В папке один Markdown-файл на запись с именем NNNN-<kebab-title>.md, индекс (по умолчанию README.md) и шаблон (по умолчанию 0000-template.md). Принятые записи неизменны, кроме метаданных; изменение заменяет запись новой, и обе ссылаются друг на друга. Статус меняется через владельца или процесс проекта. Как писать запись, описывает навык architecture-decision; навыки планирования, оркестрации и ревью спрашивают, принимает ли задача такое решение и записано ли оно.
Конфигурация¶
.embraion/decisions.yaml включает проверку и объявляет, что считается архитектурным. Пустой файл включает проверку со стандартным триггером; triggers: [] не объявляет ни одного. Файл читается из head изменения, поэтому его правки требуют такого же ревью, как любой файл политики.
index: README.md # необязательно: файл индекса в папке
template: 0000-template.md # необязательно: файл шаблона в папке
triggers: # необязательно; если задан, заменяет стандартный триггер
- id: assembly-references
paths: ["**/*.asmdef"]
changes: [modified]
patterns: ['"references"']
- id: persisted-format
paths: ["src/storage/format/**"]
extra-triggers: # необязательно; добавляется к стандартному или заданным триггерам
- id: public-contract
paths: ["src/api/**"]
extra-triggers имеет ту же форму элементов, что и triggers. Он добавляет триггеры к тому, во что разворачивается triggers, то есть к стандартному триггеру, если triggers не задан, поэтому проекту, которому нужно ещё одно правило, не нужно копировать стандартный. Id триггеров должны быть уникальны среди стандартного триггера, triggers и extra-triggers; повторяющийся id считается ошибкой. Без extra-triggers ничего не меняется.
Триггер срабатывает для изменённого файла, когда выполняется всё из следующего:
- путь файла подходит под один из
paths(глобы относительно корня репозитория;**/подходит и для нуля каталогов); - вид изменения входит в
changes(added,deleted,modified,renamed; все четыре, если не задано); переименование сопоставляется по любому из двух путей; - если задан
patterns, хотя бы одна добавленная или удалённая строка файла подходит под одно из регулярных выражений.
Стандартный триггер package-added-or-removed срабатывает, когда добавлен или удалён манифест пакета: **/package.json, **/*.asmdef, **/pyproject.toml, **/Cargo.toml, **/go.mod или **/*.csproj. Изменение манифеста стандартным триггером не является: чаще всего это обычное обновление зависимостей. Обнаружение намеренно консервативно: пропущенный триггер дёшево исправить на ревью, а ложное срабатывание на обычной работе приводит к отключению проверки. Триггеры для объявлений зависимостей, ссылок между сборками, правил владения namespace и папками, сохраняемых форматов и стабильных идентификаторов, платформенных и сборочных файлов объявляет проект.
Гейт¶
embraion decisions check --base-ref origin/main сравнивает общего предка базового ref и HEAD с HEAD. Проверка проходит, когда:
- ни один триггер не сработал (
no-trigger); - изменение добавляет или меняет Markdown-файл записи прямо в папке решений; индекс и шаблон не считаются (
recorded); - у изменения есть отказ от записи (
waived).
Иначе она падает с missing-record. Отказ от записи (waiver) — это trailer Decision-Waiver: <причина> в любом коммите изменения или параметр --waiver "<причина>", который workflow pull request может заполнять из поля описания PR. Пустая причина waiver не считается. Текст waiver попадает в отчёт, и рецензент решает, достаточна ли причина.
embraion check --base-ref <ref> запускает эту проверку, когда есть .embraion/decisions.yaml. Без --base-ref он печатает NOT RUN decisions с причиной и не падает, поэтому отсутствие базы никогда не выдаётся за успех.
Каркас записи¶
embraion adr new "Move parsing into its own package"
embraion adr new "Move parsing into its own package" --locale ru --status Proposed
Команда создаёт следующую по номеру запись из шаблона проекта, добавляет строку в индекс, а с --locale <код> создаёт рядом локализованную копию (NNNN-<title>-ru.md; если рядом с шаблоном есть 0000-template-ru.md, для неё используется он). В проекте без записей она заодно создаёт папку, шаблон и индекс; их устройство (индекс README.md с таблицей ADR | Status | Decision, статусы жизненного цикла и шаблон с разделами контекста, решения, последствий, альтернатив, проверки и внедрения) — формат, который выработали первые проекты с этим процессом, и дальше им владеет проект. Номера не переиспользуются: следующий номер выше любого номера из папки, индекса и истории папки на любом ref. Новая строка следует колонкам существующей таблицы индекса по названиям заголовков. В заголовке нужны ASCII-слова для имени файла, иначе передайте --slug. В шаблоне можно использовать {{number}}, {{title}}, {{status}} и {{date}}; --date фиксирует дату, поэтому одинаковые входные данные дают одинаковые файлы.