Files
dev-skills/lefthook.yml
T
av 872732989a адреса чужих документов сверяются с перечнем владельца
Адрес принадлежит одному плагину, а называют его все: docs/* стоит в
сорока местах конвейера, tasks/ROADMAP.md — в четырёх местах канона.
Переименование в каноне до них не доходит, и заметить это нечем:
протухший адрес попадает в механизм честной деградации ревью и выходит
правдоподобной строкой «документа в проекте нет», а не поломкой.

Перечень берётся из константы владельца — той, по которой он и так
проверяет раскладку. Судится упразднённое, а не незнакомое: список тем
канона открытый, и «нет такого имени» опровергнуть нечем; зато карта
переездов RETIRED и есть перечень запрещённого. Рядом одна догадка —
почти совпавшее имя как опечатка, порог замерен (законные до 0.64,
опечатки от 0.91).

Первый прогон: одна настоящая находка — REMAINING иллюстрировал
смысловой дубль адресом docs/specs/, упразднённым в версии 1 канона.

В гейте без glob: перечень лежит в .py, упоминания в .md, и коммит с
переименованием трогает только первую сторону.
2026-08-09 15:12:46 +03:00

63 lines
4.4 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 смотрел бы поимённо, но весь
# обход стоит сотые доли секунды — платить за него нечем.
- name: фронтматтеры
glob: "*.md"
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}