По итогам разбора собственной работы. jellybit-review-code не запускался нигде: charter обещал «проход профиля quick», а quick состоял из стадий 0, 1, 5. Проход, который нельзя запустить, нельзя и откалибровать. Теперь он стадия 1 рядом с review-specs — оба applicative, у обоих критерий записан, различаются источники (дельта-спека и конвенции). review-context.sh больше не выгружает go doc -short по всему модулю: это было 264 строки из 458 при том, что граф зависимостей — единственное, чего агент не восстановит сам, — занимает 21. Публичную поверхность он вытянет go doc по нужному месту. Из calibration.md убрана секция дополнительных метрик: precision, корреляция и стоимость прогона вручную никем не считаются, а набор показателей, который не собирают, изображает измеряемость вместо того, чтобы её давать. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
99 lines
10 KiB
Markdown
99 lines
10 KiB
Markdown
# Отчёт о переработке конвейера ревью (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.
|
||
- `scripts/review-context.sh` выгружал `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.sh` (по диффу) | — |
|
||
|
||
Правки кода под новые правила: `logging.StartCall` как единая точка отсчёта
|
||
длительности внешних вызовов, `store.Now` вместо `time.Now` в `httpapi` и
|
||
часах воркера, `slog.DiscardHandler` в тестах.
|
||
|
||
## Что осталось непокрытым намеренно
|
||
|
||
- **Ревьювер наименований** по словарю единого языка — глоссария нет, проверять
|
||
не по чему. Заводится после задачи «Словарь единого языка».
|
||
- **Дробление `review-code` на узкие оптики** — отклонено: декорреляция внимания
|
||
без декорреляции суждения почти не добавляет recall, но линейно удорожает
|
||
триаж.
|
||
- **Профиль нагрузки, история инцидентов, завязка внешних потребителей** —
|
||
недоступны ни одному проходу и остаются человеку. Перечислены в разделе
|
||
«Честный предел» скилла.
|
||
- **Калибровка проходов не проведена**: процедура заведена, первые прогоны — за
|
||
пользователем (журнал проскочивших дефектов пока пуст).
|