Files
jellybit/.claude/skills/review-pipeline/references/migration-2026-07.md
T
avandClaude Opus 4.8 776a1ca6b6 ревью: скрипты гейта на python3, шаги выбираются по изменённым файлам
gate.sh и review-context.sh переписаны на python3 — в scripts/ уже жил
diff-coverage.py, а разбор вывода git и сборка сводки на shell читались хуже,
чем работали.

Гейт больше не гоняет go-шаги впустую: build, vet, lint, gofmt, тесты, -race,
покрытие и govulncheck запускаются, только если в диффе есть .go либо
go.mod/go.sum; миграции — если тронуты миграции или код. Правка документации
проходит гейт за секунды вместо минуты. Пропуск при этом не молчит: он в сводке
с причиной и уезжает в границы покрытия, а charter гейта различает «код не
трогали» (корректно) и «инструмента нет» (настоящая дыра).

Изменённые файлы считаем как объединение диффа с базой, рабочего дерева и новых
файлов: гейт гоняют и до коммита, и после, а лишний прогон шага дешевле
пропущенного.

Заодно govulncheck перестал рапортовать «уязвимостей: 0» когда он просто не смог
отработать из-за несобирающегося кода — это SKIP, а не WARN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 19:50:40 +03:00

99 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Отчёт о переработке конвейера ревью (2026-07-23)
Что было, что стало и на основании чего. Обоснование «почему» —
[ADR-2026-07-23-review-pipeline-generative](../../../../docs/adr/ADR-2026-07-23-review-pipeline-generative.md).
## Было
Отдельного скилла ревью не существовало. Ревью — это два сабагента
(`jellybit-review-specs`, `jellybit-review-code`), вызываемые из шагов 4 и 7
`task-pipeline`, плюс дубль в финальной сверке `task-batch`. Детерминированные
проверки жили отдельно и **после** опиниативных: `lefthook` срабатывал на
коммите, `task test`/`task lint` — внутри apply.
Диагностика показала: все проходы applicative, generative нет ни одного; ни один
проход не запускает инструменты (обоим это было прямо запрещено); сверка со
спекой односторонняя; архитектурный угол судит по диффу; триажа нет; границ
покрытия нет; измерения качества нет. Плюс два мелких долга: ссылка на
несуществующий скилл `verify` и дублирующие проходы в `task-batch`.
## Стало
| Было | Стало | На основании чего |
|---|---|---|
| `task test`/`task lint` внутри apply, lefthook на коммите | **Stage 0** `jellybit-review-gate` + `task gate`: build, vet, lint, gofmt, тесты, повтор на флаки, `-race`, покрытие изменённых строк, миграции, ER-схема, gitleaks, govulncheck. Блокирует опиниативные проходы | детерминированный оракул надёжнее мнения; проверка, идущая после ревью, не защищает ревью |
| `jellybit-review-specs`: spec → code | **Stage 1** он же + **code → spec** (тихие ветки, самодеятельные дефолты, проглоченные ошибки, незаказанные ретраи), границы спеки, право сказать «требование неверно» | системная болезнь агентского кода — тихо добавленное поведение; односторонняя сверка его не видит |
| — | **Stage 2** `jellybit-review-rubric`, `jellybit-review-reimpl`, `jellybit-review-idiom`, `jellybit-review-negative` | recall чек-листа равен его длине; неявный слой достаётся только порождением критерия |
| архитектура как один из 9 буллетов `review-code`, вход = дифф | **Stage 3** `jellybit-review-architecture`, вход = `task review:context` (пакеты, граф зависимостей, инвентарь концепций) + дифф. Потолок 3 находки | агент, видящий только дифф, не знает словаря проекта и потому не может судить о втором способе делать то же самое |
| — | **Stage 4** `jellybit-review-adversary` (находка = построенный путь), `jellybit-review-ops` (условный постмортем) | враждебная постановка находит то, чего не находит перечисление свойств |
| разгребал оркестратор вручную | **Stage 5** `jellybit-review-triage`: дедуп по причине, оракул для critical/major, понижение неподтверждённого, отсев вкусовщины, потолок 7, разметка `инлайн`/`развилка` | отчёт читает оркестратор и молча реализует прочитанное: без потолка узкое место переезжает в незаказанные правки кода |
| `review-code`: 9 углов, включая механизируемое | `review-code` сжат до конвенций, **не выраженных правилом** | всё, что проверяет линтер, в промпте только отвлекает внимание |
| ревью-проходы дублировались в `task-batch` | в `task-batch` осталось **только то, что появилось от слияния**: рассинхроны на стыках + вопрос о втором способе | те же проходы на тех же файлах дают те же находки и удорожают триаж |
| ссылка на несуществующий скилл `verify` | Skill `run` | скилла `verify` нет ни в проекте, ни у пользователя — шаг молча не выполнялся |
## Что слито и что удалено
- **Слито:** архитектурный угол и стиль/дублирование выведены из
`jellybit-review-code` в отдельные проходы с разными классами дефектов;
per-capability прогон в `task-batch` сужен до стыков вместо повторного полного
ревью.
- **Удалено:** ни одного прохода. Существующий проход не удаляется без замера —
сначала калибровка (`calibration.md`), потом решение. `jellybit-review-code`
остался стадией 1 рядом с `jellybit-review-specs`: оба applicative, критерий у
обоих записан, только источники разные (дельта-спека и конвенции).
## Правка по итогам самопроверки (2026-07-23)
Разбор собственной работы нашёл три избыточности; все три устранены:
- `jellybit-review-code` **не запускался ни в одном профиле** — charter обещал
«проход профиля `quick`», а `quick` состоял из стадий 0, 1, 5. Проход, который
нельзя запустить, нельзя и откалибровать. Включён стадией 1.
- `review-context` выгружал `go doc -short` по всему модулю — 264
строки из 458. Убрано: граф зависимостей, который иначе не восстановить, — это
21 строка, а публичную поверхность агент вытянет `go doc` сам по нужному месту.
- Из `calibration.md` убрана секция «дополнительных метрик» (precision,
корреляция, стоимость): показатели, которые никто не считает, изображают
измеряемость вместо того, чтобы её давать.
Под подозрением остались `jellybit-review-idiom` (собственные правила загоняют
почти все его находки в `minor`) и половина вопросов `jellybit-review-ops`
(рост объёма в 50 раз для однопользовательского домашнего сервиса умозрителен).
Не тронуты намеренно: удалять проход по ощущению, а не по замеру — ровно то,
против чего написана процедура калибровки.
## Конвенции → правила
Механизировано и вычеркнуто из прозы (`docs/conventions/*`) и из
`openspec/config.yaml`:
| Правило | Инструмент | Откуда убрано |
|---|---|---|
| `msg` — константа, без интерполяции; стиль ключ-значение; ошибка полем | `sloglint` | logging.md |
| `slog` вместо `fmt.Print*` | `forbidigo` | logging.md |
| конфиг не из env | `forbidigo` (`os.Getenv`) | config.md |
| время только через `store.Now()` | `forbidigo` (`time.Now`) | database.md |
| `err == ErrX`, приведение типа ошибки | `errorlint` | errors.md |
| сторонние пакеты ошибок | `depguard` | errors.md |
| матчинг ошибки по тексту сообщения | `internal/archrules` | errors.md |
| `AUTOINCREMENT`, `DEFAULT (datetime('now'))` в новых миграциях | `internal/archrules` | database.md |
| транспорты не знают друг о друге, ядро не знает о транспортах | `internal/archrules` | CLAUDE.md (осталась одна строка принципа) |
| ER-схема обновлена вместе с миграцией | `scripts/gate.py` (по диффу) | — |
Правки кода под новые правила: `logging.StartCall` как единая точка отсчёта
длительности внешних вызовов, `store.Now` вместо `time.Now` в `httpapi` и
часах воркера, `slog.DiscardHandler` в тестах.
## Что осталось непокрытым намеренно
- **Ревьювер наименований** по словарю единого языка — глоссария нет, проверять
не по чему. Заводится после задачи «Словарь единого языка».
- **Дробление `review-code` на узкие оптики** — отклонено: декорреляция внимания
без декорреляции суждения почти не добавляет recall, но линейно удорожает
триаж.
- **Профиль нагрузки, история инцидентов, завязка внешних потребителей** —
недоступны ни одному проходу и остаются человеку. Перечислены в разделе
«Честный предел» скилла.
- **Калибровка проходов не проведена**: процедура заведена, первые прогоны — за
пользователем (журнал проскочивших дефектов пока пуст).