From 534572dc9c06d3607835302178a82d193796b785 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Thu, 23 Jul 2026 18:18:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=BA=D0=B8:=20ADR=20=D0=BE=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D0=B5=20=D0=BA=D0=BE=D0=BD=D0=B2=D0=B5=D0=B9=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20=D0=B8=20=D0=BE=D0=B1=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B1=D0=B5=D0=BA?= =?UTF-8?q?=D0=BB=D0=BE=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR фиксирует «почему»: recall чек-листа равен его длине, ценность верификатора определяется оракулом и декорреляцией с автором (а не числом ролей), отчёт без границ покрытия хуже отсутствия отчёта. В беклоге закрыт открытый вопрос «дробить ли review-code на узкие оптики» — не дробим; осталась калибровка проходов и ревьювер наименований. Co-Authored-By: Claude Opus 4.8 (1M context) --- ...R-2026-07-23-review-pipeline-generative.md | 88 +++++++++++++++++++ docs/adr/README.md | 1 + docs/backlog/README.md | 2 +- docs/backlog/agenty-revyuvery-kachestva.md | 37 ++++++-- 4 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 docs/adr/ADR-2026-07-23-review-pipeline-generative.md diff --git a/docs/adr/ADR-2026-07-23-review-pipeline-generative.md b/docs/adr/ADR-2026-07-23-review-pipeline-generative.md new file mode 100644 index 0000000..8befc16 --- /dev/null +++ b/docs/adr/ADR-2026-07-23-review-pipeline-generative.md @@ -0,0 +1,88 @@ +# Конвейер ревью: гейт, generative-проходы и обязательный триаж + +- Дата: 2026-07-23 + +## Контекст + +Ревью изменений вели два сабагента (`jellybit-review-specs`, +`jellybit-review-code`), вызываемые из `task-pipeline`. Оба устроены одинаково: +получают дифф и применяют записанный чек-лист — конвенции, инварианты, пункты +дельта-спеки. Инструменты им запускать было запрещено, детерминированные +проверки (`lefthook`, `task test`/`task lint`) шли отдельно и **после** +опиниативных проходов. + +У такой конфигурации три ограничения, которые нельзя снять её же средствами. + +**Recall чек-листа равен длине чек-листа.** Проход, устроенный как «проверь +пункты 1..N», находит ровно перечисленное. Всё неявное — форма решения, +идиоматичность, «так не делают» — неперечислимо по определению: то, что можно +выписать, уже стало бы конвенцией. Удлинение списков не помогает, а вредит: +внимание уходит на именование полей лога и не доходит до формы решения. + +**Ценность верификатора определяется наличием внешнего оракула и декорреляцией +с автором, а не числом ролей.** Разделение на «архитектура / конвенции / стиль» +декоррелирует внимание, но не суждение: под всеми ролями одна модель с одними +априорными, и код писала она же. Бюджет уходил на мнения при непокрытом уровне +детерминированных инструментов (`-race`, покрытие изменённых строк, флаки, +`govulncheck` не гонялись вовсе). + +**Отчёт без границ покрытия хуже отсутствия отчёта.** «Замечаний нет» +потребляло ощущение проверенности, ничего не гарантируя. + +Дополнительно: сверка со спекой шла только в направлении spec → code, поэтому +поведение, которое код имеет, а дельта не заказывала, не ловилось никем — а это +системная болезнь агентского кода. Измерения качества ревью не существовало. + +## Рассмотренные варианты + +- **Дробить `jellybit-review-code` на узкие оптики** (архитектура / конвенции / + стиль) — так стоял открытый вопрос в беклоге. Отвергнуто: добавляет роли, не + добавляя ни оракула, ни декорреляции суждения; recall почти не растёт, а + стоимость триажа растёт линейно. +- **Удлинять чек-листы и конвенции** — прямо противоположно причине проблемы. +- **Заменить конвейер CI-проверками** — покрывает только выразимое правилом; + неявный слой остаётся непокрытым. + +## Решение + +Конвейер пересобран по типу проходов, а не по ролям, и оформлен скиллом +`.claude/skills/review-pipeline`. + +1. **Детерминированный гейт первым** (`task gate`): агент запускает инструменты + и интерпретирует вывод, отличая новые отказы от унаследованных. Пока гейт + красный, опиниативные проходы не запускаются. Гейт также выдаёт находки + класса «отсутствующая верификация» — непокрытые изменённые строки, + конкурентность без параллельного теста, флаки. +2. **Сверка со спекой двунаправленная**, причём code → spec важнее: ищем + поведение, которого дельта не заказывала, и классифицируем — дописать спеку + или починить код. Проходу явно разрешено сомневаться в самом требовании. +3. **Generative-проходы** как отдельный слой: рубрика до чтения кода, + независимая реализация без подглядывания, заземление идиоматичности на + stdlib и поимённые положения гайдов, негативное пространство. Только они + достают то, чего нет ни в одном списке. +4. **Обязательный триаж** с потолком 7 находок и разметкой `инлайн`/`развилка`. + Отчёт читает оркестратор и молча реализует прочитанное, поэтому потолок + защищает кодовую базу от незаказанных правок, а не внимание человека. +5. **Храповик**: находка → конвенция → правило линтера → **удаление из прозы и + промптов**. Третий шаг обязателен; в конвенциях остаётся только то, что + правилом не выражается. +6. **Измеримость**: журнал проскочивших дефектов и калибровка инъекцией с + вердиктами `keep`/`retune`/`drop`. Проход, не находящий дефект своего класса + в 2 из 3 прогонов после двух правок промпта, удаляется, а не правится дальше. + +## Последствия + +- `+` У ревью появился объективный оракул там, где он вообще возможен, и явная + граница между «проверено», «не проверялось» и «недоступно в принципе». +- `+` Неявный слой (форма решения, лишние абстракции, отсутствующее) стал + предметом отдельных проходов, а не побочным эффектом чтения диффа. +- `+` Механизируемое ушло в `.golangci.yml` и `internal/archrules`: конвенции и + промпты разгружены, правило проверяется бесплатно и всегда. +- `-` Профиль `deep` заметно дороже прежнего ревью по токенам и времени; отсюда + профили и правило выбора по факту изменения. +- `-` Generative-проходы шумят: без триажа они делают хуже, чем ничего. + Триаж стал обязательным элементом, а не опцией. +- `-` Набор проходов теперь нужно **измерять**, иначе он вырождается в театр. + Журнал заполняется по горячим следам, ретроспективные записи бесполезны. +- Как следствие: калибровку проходов надо провести на реальных пробах — + процедура заведена, первые прогоны за владельцем. diff --git a/docs/adr/README.md b/docs/adr/README.md index 53fdc7a..bdfe918 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -56,6 +56,7 @@ | Дата | Запись | Статус | | ---------- | ---------------------------------------------------------------- | ------ | +| 2026-07-23 | [Конвейер ревью: гейт, generative-проходы и триаж](ADR-2026-07-23-review-pipeline-generative.md) | — | | 2026-06-13 | [Авто-раскладка только при матче в метабазе](ADR-2026-06-13-auto-link-requires-db-match.md) | — | | 2026-06-13 | [Docker как единица деплоя](ADR-2026-06-13-docker-deploy.md) | — | | 2026-06-13 | [Хардлинки вместо копирования и симлинков](ADR-2026-06-13-hardlinks.md) | — | diff --git a/docs/backlog/README.md b/docs/backlog/README.md index 5dd08e0..dac3492 100644 --- a/docs/backlog/README.md +++ b/docs/backlog/README.md @@ -23,7 +23,7 @@ Tududi (проект `jellybit`) больше **не** держит беклог ## Средний - [Словарь единого языка (ubiquitous language)](ubiquitous-language-slovar.md) — Свести термины домена в один глоссарий, чтобы пользователь, документация, код и агент… -- [Агенты-ревьюверы качества (наименования, архитектура, конвенции, стиль)](agenty-revyuvery-kachestva.md) — Ядро (specs+code ревьюверы) сделано и вшито в task-pipeline; остался ревьювер наименований (ждёт словарь единого языка) +- [Агенты-ревьюверы качества (наименования, архитектура, конвенции, стиль)](agenty-revyuvery-kachestva.md) — Конвейер `review-pipeline` переработан (гейт, generative-проходы, триаж); осталась калибровка проходов и ревьювер наименований (ждёт словарь единого языка) - [[идея] Сила совпадения кандидата и пересмотр распознавания/матчинга](sila-sovpadeniya-kandidata.md) — ИДЕЯ (сперва проработать) - [История переходов загрузки](istoriya-perehodov-zagruzki.md) — Сохранять полную историю переходов состояний загрузки (что/когда/почему/кто инициировал… - [Привязка уведомлений к источнику в ботах (мульти-бот)](uvedomleniya-multi-bot.md) — Уведомления и запросы подтверждения должен получать тот, кто прислал загрузку: автор… diff --git a/docs/backlog/agenty-revyuvery-kachestva.md b/docs/backlog/agenty-revyuvery-kachestva.md index 8d8da95..fd8f141 100644 --- a/docs/backlog/agenty-revyuvery-kachestva.md +++ b/docs/backlog/agenty-revyuvery-kachestva.md @@ -2,23 +2,42 @@ **Приоритет:** средний -Набор узких сабагентов-ревьюверов поверх ревью-процесса из CLAUDE.md, каждый со своей оптикой: соответствие наименований словарю единого языка, соблюдение архитектурных границ (единое ядро/тонкие транспорты, инварианты безопасности данных), конвенций (ошибки, логирование, конфиг, TZ), стиля кода и поиск дублирования. Запускаются как чекпоинт перед archive/коммитом. Развивает ревью-процесс OpenSpec в сторону воспроизводимых автопроверок, не заменяя человеческое ревью. +Набор сабагентов-ревьюверов поверх ревью-процесса из CLAUDE.md. Развивает +ревью-процесс OpenSpec в сторону воспроизводимых автопроверок, не заменяя +человеческое ревью. ## Сделано (2026-07-10) - Заведены два кастомных ревьювера в `.claude/agents/`: `jellybit-review-specs` (оптика спек/требований) и `jellybit-review-code` (архитектура, инварианты, конвенции, стиль, дублирование). -- Оба подключены как чекпоинт в скилл `.claude/skills/task-pipeline` (ревью спек - ДО кода + ревью кода перед archive; на тривиальной задаче — один - `jellybit-review-code`, на нетривиальной — оба параллельно). +- Оба подключены как чекпоинт в скилл `.claude/skills/task-pipeline`. + +## Сделано (2026-07-23) — переработка конвейера + +Конвейер пересобран по типу проходов, а не по ролям: скилл +`.claude/skills/review-pipeline` (гейт → сверка со спекой в обе стороны → +generative-проходы → архитектура → враждебные постановки → триаж), профили +`quick`/`standard`/`deep`/`design`, контракт находок, границы покрытия, +храповик «находка → конвенция → правило → удаление», журнал проскочивших +дефектов и процедура калибровки. Подробности — ADR +[ADR-2026-07-23-review-pipeline-generative](../adr/ADR-2026-07-23-review-pipeline-generative.md) +и отчёт о миграции в `references/migration-2026-07.md` скилла. + +Открытый вопрос «дробить ли `jellybit-review-code` на узкие оптики» закрыт: +**не дробим** — декорреляция внимания без декорреляции суждения почти не +добавляет recall, но линейно удорожает триаж. ## Осталось - **Ревьювер наименований** (соответствие словарю единого языка) — отдельной - оптикой пока не выделен: зависит от задачи «Словарь единого языка - (ubiquitous language)», без глоссария проверять не по чему. Завести после неё. -- По опыту эксплуатации — решить, дробить ли `jellybit-review-code` на более - узкие оптики (архитектура / конвенции / стиль+дублирование) или оставить одним. + оптикой не выделен: зависит от задачи «Словарь единого языка (ubiquitous + language)», без глоссария проверять не по чему. Завести после неё. +- **Калибровка проходов** по процедуре + `.claude/skills/review-pipeline/references/calibration.md` — ни один проход + ещё не замерен инъекцией. До замера ничего не удаляем и промпты не правим. +- **Заполнить журнал** `docs/review/journal.md` случаями, которые уже + проскочили ревью, — они станут первыми пробами калибровки. -Связано: CLAUDE.md (ревью-процесс, конвенции), docs/conventions, «Словарь единого языка», скилл `task-pipeline`. +Связано: CLAUDE.md (ревью-процесс, конвенции), docs/conventions, «Словарь +единого языка», скиллы `review-pipeline`/`task-pipeline`/`task-batch`.