# finetooth

Сплошное ревью всего репозитория блоками: карта покрытия «файл → блок», гипотезы как второй знаменатель, три роли агентов (охотник, проверяющий, исполнитель) и состояние на диске, которое переживает смену сессий.

*#ревью #аудит #агенты #скилл #качество-кода*

> miki/finetooth · v5 · `7b28ca43151a279e38de02fb48e0378b2013a7c2`

Ревью всего кода, а не диффа: репозиторий режется на блоки, каждый блок проходят четыре роли — охотник, проверяющий, исполнитель, ревьюер починки, — а полноту доказывает карта покрытия: ни одного файла без блока.

Сессии меняются, контекст кончается, поэтому **всё состояние живёт на диске** в `docs/review/` проекта и читается обратно инструментом. Ничего не держи в памяти переписки.

Основатель метода — **Георгий Худобандаев**: набор родился на его проекте, и всё устройство пришло оттуда. Исходный код, тесты и история изменений — [github.com/mikey-semy/finetooth](https://github.com/mikey-semy/finetooth) (там же ставится одной командой: `npx skills add mikey-semy/finetooth`). Лицензия MIT на обоих авторов, полный текст — в `references/LICENSE`.

Все действия — через `scripts/review.py` скилла, **запущенный из корня ревьюируемого репозитория**: корень берётся у git по рабочему каталогу. Нужны git и Python 3, только стандартная библиотека.

Ниже инструмент называется `review`: поставленный в проект, он лежит в `.claude/skills/finetooth/scripts/review.py`. Если в `docs/review/blocks.json` есть поле `cli` — проект зовёт инструмент по-своему (`npm run review --`, `make review`), используй его.

Сообщения самого инструмента — по-английски. Язык промптов ролей и образцов задаёт поле `lang` в `blocks.json` (`en` по умолчанию, `ru`): русские шаблоны лежат рядом с английскими с суффиксом `.ru.md`.

Каждый отказ инструмента сам называет команду, которой он исправляется: читай отказ, а не угадывай.

1. **Посмотреть, где остановились**
   В репозитории уже есть `docs/review/` — значит, ревью идёт. Не начинай своё параллельное.

`review status` — где мы и какой блок следующий; `review next` — его id.
   > Why: Состояние на диске, а не в памяти прошлой сессии.

2. **Проверить, что состояние непротиворечиво**
   `review check`.
   > Why: Работа поверх противоречивого состояния множит ошибки: блок, закрытый на другой версии кода, выглядит пройденным.
   - [ ] Всё красное починено до начала новой работы

3. **Прочитать дневник**
   `docs/review/journal.md` — что решили до тебя и почему.
   > Why: Находки восстановимы повторным прогоном, решения — нет.

4. **Собрать скелет ревью**
   `review setup --project <Имя>` — скелет `blocks.json`, `invariants.md` и точка входа `docs/review/README.md`. Если проект зовёт инструмент по-своему, добавь `--cli "<команда>"`; для русских промптов и образцов — `--lang ru`.

5. **Записать инварианты проекта**
   `docs/review/invariants.md` — правила ЭТОГО проекта. Вклеивается каждому агенту и решает, что тот сочтёт дефектом.
   > Why: Общие слова бесполезны: «код должен быть корректным» не помогает агенту отличить находку от придирки. Пиши то, за что проект уже заплатил.
   - [ ] Каждое правило выведено из случившегося, а не из общих соображений
   - [ ] Есть раздел о продакшене, старых данных и целевом масштабе

6. **Нарезать репозиторий на блоки**
   В `docs/review/blocks.json` — `gates` (команды ворот проекта) и блоки: сквозные сначала, доменные потом, стендовые последними. `review inventory` печатает дерево репозитория с размерами и владением — нарезай по нему; `review sizes` показывает блоки выше порога.

Блок, который чтение не докажет (качество тестов, производительность, сканеры), получает `"proof": "measured"`: доказательство — артефакты из манифеста, порог на него не действует. Блок без `paths` — живой стенд. Образец — `assets/blocks.example.json`.
   > Why: Блок — то, что читается за один сеанс: порог `readable_lines`, по умолчанию 6000 строк. Больше — и отчёт соврёт про охват.
   - [ ] Ни один читаемый блок не превышает порог строк

7. **Довести покрытие до нуля непокрытых**
   `review init`, затем `review coverage` — разбирай непокрытые файлы, пока их не станет ноль.
   > Why: Файл в блок относит человек: попавший по совпадению шаблона будет числиться прочитанным, не будучи прочитанным.
   - [ ] `coverage` сообщает: непокрытых файлов нет

8. **Написать манифест блока**
   `docs/review/blocks/<ID>-<слаг>.md`: зачем блок, что считается находкой, пронумерованные гипотезы про этот проект, критерий приёмки. Образец — `assets/manifest.example.md`.
   > Why: Без проектных гипотез ревью выходит «по общим соображениям». Эту часть не срезать.
   - [ ] 10–15 гипотез именно про этот проект
   - [ ] Критерий приёмки нельзя выполнить, не прочитав код

9. **Пустить охотника**
   `review prompt <ID> --role hunter` печатает готовый промпт — отдай его субагенту **целиком и без правок**. Агент сам пишет отчёт и черновик находок на диск. Затем `review set-status <ID> hunted`.

10. **Пустить проверяющего — другим агентом**
    `review prompt <ID> --role verify`. Проверяет каждую находку исполнением, делает свой проход по самому опасному, перезаписывает файл находок. Затем `review set-status <ID> verified`.
    > Why: Ценность второй роли — не в фильтре, а в углублении; и работает она, только когда исполняет, а не перечитывает.
    - [ ] Отвергнутые находки не удалены — остались с причиной

11. **Принять блок самому**
    Прочитай оба отчёта и сверь с критерием приёмки.
    > Why: Отчёт агента отвечает «файл открывали», а критерий — «вопрос решён».
    - [ ] Критерий приёмки выполнен
    - [ ] Охват неполный — блок ушёл на повторный проход, а не в закрытие

12. **Занести находки в реестр**
    `review import <ID>`, `review findings`, `review check`.

13. **Записать решение в дневник — сразу**
    `review log <ID> "что решили и почему"`.
    > Why: Что решили и почему — не восстанавливается ничем, кроме этой записи.

14. **Починить — ещё одним агентом**
    `review prompt <ID> --role fix`. Режь задания по связным областям, а не по одной находке. Ворота и проверку откатом прогоняй сам после исполнителя. Находки переводятся `review set-finding <ID…> fixed --commit <sha>` (несколько id разом); отложить можно только с причиной (`deferred --reason`).
    > Why: Класс дефекта с третьим экземпляром закрывается уздой (`--rule <путь к тесту или правилу>`), а не списком правок: иначе четвёртый придёт на следующей неделе.

15. **Отдать правки ревьюеру — свежему агенту**
    `review prompt <ID> --role fixreview --diff main...HEAD [--round N] [--scope половина]`. Дифф вклеивается в промпт целиком; два агента на две половины диффа — нормально. Подтверждённые находки ревьюера заносятся добором (`import <ID> --append`), даже уже починенные.
    > Why: Правки пишет исполнитель, а смотрит тот, кто их не писал. Круги повторяются, пока ревьюер отвечает «следующий круг нужен»; круг, нашедший дефект, внесённый прошлым кругом, — сигнал остановиться и подумать.

16. **Закрыть блок**
    `review set-status <ID> closed` — только после отчёта ревьюера правок.
    > Why: Без отчёта ревьюера правок блок с починками закрыть нельзя: `review check` это держит.

**Один агент не ищет и не чинит одновременно.** Чинит не тот, кто нашёл; проверяет не тот, кто чинил. Повторную починку — свежему агенту, не тому же: задание самодостаточно, а ошибки первого захода — ошибки внимания.

**Граница блока — полная остановка:** доложить владельцу и ждать команды на следующий. Открытый вопрос повторяется целиком, у каждого — кто решает и рекомендация.

**Блок не закрывается** без выполненного критерия приёмки и без отчёта проверяющего.

**Проверка за пределами своего репозитория — против свежего `origin` после `git fetch`.** Отставшее дерево показывает починенное как сломанное.

**Никаких ссылок на ревью в коде:** номера находок и блоков умрут вместе с `docs/review/`.

**Больше двух-трёх агентов разом не запускать**, если на машине идёт сборка.

Проверка красная — работа не сделана, даже если так кажется. Она ловит, среди прочего:

- файл без блока и устаревшую карту покрытия; шаблон блока, под который попадают только нетрекнутые файлы;
- файл читаемого блока, не названный полным путём ни в одном отчёте;
- гипотезу без вердикта или с противоречивыми вердиктами;
- отчёт охотника без раздела «Границы охвата» и пустой отчёт проверяющего;
- отложенную находку без причины, блок в `blocked` без записки, фазы не по порядку;
- закрытый с починками блок без ревью правок;
- блок и находку, закрытые на другой версии кода (отпечатки — `review restamp`, если правки к делу не относятся; `review backfill` — для записей старше отпечатков);
- находку без причины отказа, коммит починки, не трогающий файл, дубль несуществующей находки, узду по несуществующему пути;
- дерево, отставшее от сервера больше чем на неделю.

17. **Убрать docs/review/ одним изменением и оставить итог**
    Все блоки `closed`, открытых находок нет, у каждой отвергнутой — причина. Долговечное переезжает: правила — в корневой файл инструкций, решения — в ADR, проверки — в тесты.
    > Why: Каталог ревью — леса вокруг стройки, а не часть здания. Но без итога следующее ревью начнётся с нуля.
    - [ ] Остался один файл-итог: дата и коммит-база, блоки и их критерии, отвергнутые находки с причинами, чем закрыт каждый класс дефектов

- `references/hunter.md`, `verify.md`, `fix.md`, `fixreview.md` — шаблоны ролей (английские; русские рядом — `<роль>.ru.md`, выбираются по `lang`). Промпт из них собирает `review prompt`; читать их нужно, только чтобы понять или поправить роль. Проект может держать свою версию в `docs/review/prompts/<роль>.md` — тогда берётся она.
- `references/lessons.md` — уроки двух ревью, из которых выросли правила: читать до первого блока.
- `references/LICENSE` — MIT, оба автора.
- `assets/` — образцы (тоже в двух языках): блоки, манифест, инварианты, дневник, баннер для корневого файла инструкций, цели `make` и `package.json`, пример узды.
