- «готовность» значила и «запись можно брать», и «что считается сделанным»; второй смысл стал «определением сделанного» — своё же правило про занятое слово запрещало это прямо - «пайплайн» жил в 24 местах вне журналов при том, что DECISIONS фиксирует его уход «целиком»; рабочее имя — конвейер - «чекпоинт» в review значил стадию и проход, в resolve — остановку человеку; слово оставлено за остановкой - у описания плагина было два дома, и три из четырёх уже разошлись. Сведены, и класс закрыт машиной: frontmatter.py сверяет plugin.json с marketplace, гейт разбужен на *.json - README врал про односторонние зависимости и терял healthcheck на диаграмме - перечень агентов в REMAINING отстал на два поколения Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
66 lines
4.8 KiB
YAML
66 lines
4.8 KiB
YAML
# Гейт коммита: всё, что в этом репозитории проверяется машиной.
|
||
#
|
||
# Документы — то, что читает не человек, а машина, и чья поломка **не видна при
|
||
# чтении**: фронтматтер (его разбирает загрузчик скиллов), помеченная копия
|
||
# правила (расходится молча) и диаграмма mermaid (текст правдоподобен, рендер
|
||
# падает). Скрипты — ruff и pyrefly: они же стерегут ноль внешних зависимостей,
|
||
# без которого tasks.py и docs.py перестают работать в чужом проекте.
|
||
# Всё остальное (проза, устройство, язык) — предмет ревью, а не хука.
|
||
#
|
||
# **Что судится — staged-файлы, а не рабочее дерево**, всюду, где проверка
|
||
# умеет смотреть поимённо: гейт обязан судить то, что уедет в историю, а не то,
|
||
# что случайно лежит на диске рядом. Три исключения названы у своих задач, и все
|
||
# — про то, что проверке нужен весь репозиторий по существу, а не для удобства.
|
||
#
|
||
# Ставится `lefthook install` (см. README, «Гейт коммита»). Обойти разово —
|
||
# `LEFTHOOK=0 git commit …`; обход законен ровно для того случая, когда чинить
|
||
# найденное нечем прямо сейчас.
|
||
|
||
pre-commit:
|
||
parallel: true
|
||
jobs:
|
||
# Обе проверки документов идут по всему репозиторию, и это не недосмотр.
|
||
# copies.py сверяет копию с домом, а дом лежит в другом файле, которого в
|
||
# индексе может не быть: список staged дал бы «копии дословны» там, где
|
||
# правка дома их и разошлась. frontmatter.py смотрел бы поимённо, но весь
|
||
# обход стоит сотые доли секунды — платить за него нечем. Glob у него шире
|
||
# на `*.json`: тем же проходом сверяется `description` плагина в
|
||
# `plugin.json` с записью того же плагина в `marketplace.json`, а коммит,
|
||
# правящий только манифест, по глобу `*.md` проверку бы не разбудил.
|
||
- name: фронтматтеры
|
||
glob: "*.{md,json}"
|
||
run: python3 scripts/frontmatter.py
|
||
|
||
- name: копии правил
|
||
glob: "*.md"
|
||
run: python3 scripts/copies.py
|
||
|
||
# Без glob намеренно, и это третье исключение из правила «судим staged».
|
||
# Проверка сводит две стороны: перечень адресов лежит в константе скрипта
|
||
# владельца (`.py`), упоминания — в прозе плагинов (`.md`). Коммит, где
|
||
# переименован документ канона, трогает только первую сторону: по глобу
|
||
# `*.md` он бы проверку не разбудил, а расходится в нём именно вторая.
|
||
# Весь обход — семь сотых секунды.
|
||
- name: адреса документов
|
||
run: python3 scripts/addresses.py
|
||
|
||
# Самая дорогая проверка: каждый блок — свой запуск mermaid-cli со своим
|
||
# chromium. Отсюда и staged-файлы вместо обхода, и параллель внутри самого
|
||
# скрипта: репозиторий целиком — 3 секунды, один файл — одна.
|
||
- name: диаграммы
|
||
glob: "*.md"
|
||
run: python3 scripts/diagrams.py {staged_files}
|
||
|
||
# Линтеры — через uv: версии прибиты точно, и `uv run` берёт именно их, а не
|
||
# то, что оказалось в PATH. `--fix` чинит безопасное сам, `stage_fixed`
|
||
# доносит починку до этого же коммита — иначе она осталась бы в рабочем
|
||
# дереве, а в историю уехал бы невычищенный файл.
|
||
- name: ruff
|
||
glob: "*.py"
|
||
stage_fixed: true
|
||
run: uv run ruff check --fix {staged_files}
|
||
|
||
- name: pyrefly
|
||
glob: "*.py"
|
||
run: uv run pyrefly check {staged_files}
|