- скилл project-brief: бриф собирается из CLAUDE.md, архитектуры, Taskfile и конвенций и показывается человеку. Раньше единственная инструкция по его созданию лежала внутри шаблона, поэтому деградированный режим был не аварийным, а единственным: critical по основанию «нарушен инвариант» недостижим ни на одной задаче - rebase перенесён внутрь worktree задачи: прежняя форма падала на занятой ветке, и агент уводил весь батч в провалившиеся с ложной причиной - контракт брифа дополнен восемью слотами; проверен заполнением на обоих проектах, незаполнимых нет. Прецедент healthlog вынут из общего charter'а в бриф — там он вмёрз вместе с числами - шов: пайплайн задачу не закрывает и записи учёта не трогает, урожай отдаёт списком, правило остатка — ссылкой на av-dev-tasks - деградированный абзац во всех девяти проходах, вопрос 9 в ops, пространство имён в вызовах, раздел предпосылок
452 lines
40 KiB
Markdown
452 lines
40 KiB
Markdown
---
|
||
name: review-pipeline
|
||
description: Конвейер ревью изменения — детерминированный гейт, сверка с дельта-спеками в обе стороны, враждебные постановки и эксплуатационный постмортем, независимая реализация по триггеру, архитектура и обязательный триаж. Проходы гонятся последовательно; параллельно — только по явной просьбе и с явно названным набором. Проектная специфика приходит из файла-брифа. Вызывается из task-pipeline (чекпоинты ревью), из task-batch (финальная сверка) и отдельно — профилем design на предложении ДО кода.
|
||
---
|
||
|
||
# Конвейер ревью
|
||
|
||
Готовит ревью — **не заменяет его**. Потребитель отчёта — оркестратор, который
|
||
чинит код; человек читает только сводку, развилки и границы покрытия.
|
||
|
||
## Три правила, из которых всё следует
|
||
|
||
Если ситуация не покрыта инструкцией — решай по ним.
|
||
|
||
1. **Recall чек-листа равен длине чек-листа.** Проход, устроенный как «проверь
|
||
пункты 1..N», найдёт ровно перечисленное. Всё неявное — идиомы, форма
|
||
решения, «так не делают» — неперечислимо по определению: перечислимое уже
|
||
стало бы конвенцией. Отсюда деление проходов на **applicative** (применяют
|
||
заданный критерий) и **generative** (сперва порождают критерий или
|
||
альтернативу, потом сравнивают). Расширять чек-листы бесполезно; неявный слой
|
||
достают только generative-проходы.
|
||
2. **Ценность верификатора = наличие внешнего оракула × декорреляция с
|
||
автором**, а не число ролей. Под всеми ролями одна модель с одними
|
||
априорными, вход у всех общий: седьмая роль почти не добавляет recall, но
|
||
линейно удорожает триаж. Иерархия надёжности: детерминированный инструмент >
|
||
агент, который его **запускает** и интерпретирует вывод > агент с чистым
|
||
мнением. Максимум работы переносим вниз.
|
||
3. **Отчёт без границ покрытия хуже отсутствия отчёта.** «Критичных проблем не
|
||
обнаружено» потребляет ощущение проверенности, ничего не гарантируя. Секция
|
||
границ покрытия обязательна и не сокращается — в том числе в докладе человеку.
|
||
|
||
## Предпосылки
|
||
|
||
Конвейер опирается на внешнюю обвязку и без неё работает не целиком. Проверь это
|
||
один раз, при установке плагина в проект:
|
||
|
||
- **OpenSpec и скиллы `opsx:*`.** Профиль `design`, проход `review-specs` и
|
||
вызывающий пайплайн задачи завязаны на дельта-спеки
|
||
(`openspec/changes/<id>/specs/*/spec.md`), на актуальные спеки
|
||
(`openspec/specs/`) и на `openspec validate --strict`. В проекте без OpenSpec
|
||
шаги, зовущие `opsx:explore` / `opsx:propose` / `opsx:apply` / `opsx:archive`,
|
||
упадут на «нет такого скилла», а `review-specs` останется без источника
|
||
требований. Такой проект либо подключает OpenSpec, либо сознательно не зовёт
|
||
`review-specs` и профиль `design` — и тогда это идёт строкой «не запускался» в
|
||
границы покрытия, как любой другой пропуск.
|
||
- **Бриф проекта** — см. следующий раздел. Заводится скиллом, а не руками.
|
||
- **Проектные копии этих скиллов и агентов удаляются при установке.** Если в
|
||
проекте уже лежат свои `.claude/skills/review-pipeline`,
|
||
`.claude/skills/task-pipeline`, `.claude/skills/task-batch` или
|
||
`.claude/agents/<проект>-review-*.md` — снеси их. Иначе короткое имя разрешится
|
||
в устаревшую проектную копию, молча и без признаков подмены. По той же причине
|
||
**скиллы этого плагина зовутся с пространством имён**:
|
||
`av-dev-pipeline:review-pipeline`, `av-dev-pipeline:task-pipeline`,
|
||
`av-dev-pipeline:task-batch`, `av-dev-pipeline:project-brief`.
|
||
|
||
## Что конвейер защищает — приходит из брифа
|
||
|
||
Проходы общие, а нарушать нельзя проектное. Список инвариантов, команду гейта,
|
||
объёмы, прецеденты и модель угроз конвейер **не знает** — он читает их в брифе
|
||
проекта: [references/project-brief.md](references/project-brief.md) описывает
|
||
контракт, [references/brief-template.md](references/brief-template.md) — образец
|
||
заполнения.
|
||
|
||
Разреши путь к брифу один раз, в начале прогона: путь из задания →
|
||
`docs/review-brief.md` → `.claude/review-brief.md`. Дальше передавай готовым.
|
||
|
||
**Брифа нет по всем трём путям — заведи его, а не понижай прогон.** Вызови Skill
|
||
**`av-dev-pipeline:project-brief`**: он соберёт бриф из `CLAUDE.md`, архитектуры,
|
||
файла задач и конвенций, покажет человеку и вернёт путь. Это механика, а не
|
||
развилка: спрашивать разрешения не нужно, и остановка прогона тут не
|
||
предусмотрена. Заведение стоит одного шага один раз на проект — деградированный
|
||
режим платит на каждой задаче.
|
||
|
||
**Деградированный режим — исход, а не умолчание.** Он включается ровно тогда,
|
||
когда бриф завести не удалось (репозиторий на чтение, человек прямо запретил,
|
||
инварианты вывести неоткуда): `critical` по основанию «нарушен инвариант
|
||
проекта» никем не присваивается, числа объёма не используются, и в границы
|
||
покрытия уезжает строка «брифа проекта нет, завести не удалось: <причина>».
|
||
Причина обязательна — без неё строка неотличима от «мы просто не стали».
|
||
|
||
## Что получает каждый проход
|
||
|
||
Задание любому проходу состоит из шести вещей, и первая — главная: без брифа
|
||
проход теряет предмет проверки и уходит в деградированный режим.
|
||
|
||
- **бриф** — путь (разрешён или заведён на старте, см. выше);
|
||
- **контракт находок** — путь к
|
||
[references/finding-contract.md](references/finding-contract.md) (в
|
||
установленном плагине — `${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/`);
|
||
- **изменение** — идентификатор change и путь к его дельта-спекам;
|
||
- **база диффа**;
|
||
- **профиль и режим** прогона — чтобы проход знал, что писать в границы покрытия;
|
||
- **сужение**, если оно есть: конкретный узел, конкретная capability.
|
||
|
||
Чего проход **не** получает ни в каком режиме — выводов других проходов. См.
|
||
«Режим запуска».
|
||
|
||
## Модель по проходу
|
||
|
||
Следует из правила 2: чем больше работы делает детерминированный инструмент,
|
||
тем дешевле может быть модель; чем больше проход **порождает** критерий, тем
|
||
дороже. Модель задана во frontmatter каждого агента, менять её здесь не нужно.
|
||
|
||
| Модель | Проходы | Почему |
|
||
|---|---|---|
|
||
| `sonnet` | gate, code, ops | вход структурный, критерий записан заранее |
|
||
| `opus` | specs, adversary, rubric, reimpl | суждение без опоры на инструмент |
|
||
| `fable` | triage, architecture | ошибка распространяется дальше самой находки |
|
||
|
||
**Самая дорогая модель — только двум проходам, и это калибровка, а не
|
||
осторожность.** Замер: на первом же прогоне конвейера самые ценные находки дали
|
||
`opus`-проходы — сверка спек дала 13 находок с оракулами, а проход про
|
||
идиоматичность (впоследствии упразднённый) — три эксперимента против драйвера БД
|
||
с воспроизведёнными числами. Разницы в пользу более дорогой модели на
|
||
опиниативных проходах не обнаружилось — значит платить за неё там не за что.
|
||
|
||
Двое, у кого она остаётся, отобраны по одному признаку: **их ошибка
|
||
распространяется дальше собственной находки.**
|
||
|
||
- `triage` — через него проходит всё, что оркестратор реализует **молча**:
|
||
ложноположительная находка становится кодом, потерянный `critical` — дефектом.
|
||
Ошибка триажа дороже ошибки любого отдельного прохода.
|
||
- `architecture` — запускается редко (только `deep` и `design`), потолок в
|
||
3 находки делает его дешёвым по выходу, а находка на предложении стоит абзаца
|
||
против переписывания на готовом коде. Дёшево × высокое плечо.
|
||
|
||
`reimpl` намеренно **не** в этом списке, хотя он самый ценный из generative: его
|
||
стоимость определяется объёмом вывода (он пишет реализацию целиком), так что
|
||
дорогая модель множит самый большой счёт. Ценность же его — в **независимости**
|
||
взгляда, а не в мощности модели.
|
||
|
||
**Самая дешёвая модель не используется ни на одном проходе, и это не экономия
|
||
наоборот.** Дешёвая модель на опиниативном проходе даёт правдоподобные находки,
|
||
которые триаж обязан опровергать оракулом, — а это самая дорогая операция
|
||
конвейера. Механизируемая же работа здесь вынесена **ниже** модели: гейт,
|
||
покрытие диффа, карта проекта — это скрипты проекта, они стоят ноль токенов.
|
||
Дешёвому проходу просто не осталось работы.
|
||
|
||
Экономия достигается не понижением модели, а **непуском прохода**: `quick` —
|
||
четыре прохода, `deep` — семь-восемь. Правило выбора профиля и есть главный
|
||
рычаг стоимости.
|
||
|
||
## Профили
|
||
|
||
| Профиль | Когда | Стадии | Проходов |
|
||
|---|---|---|---|
|
||
| `quick` | багфикс, локальная правка, доки | 0, 1, 5 | 4 |
|
||
| `standard` | новая функциональность в существующем пакете | 0, 1, 2, 5 | 6 |
|
||
| `deep` | новый пакет, изменение публичного контракта, миграция схемы, трогает инварианты брифа | 0, 1, 2, 3, 4, 5 | 7–8 |
|
||
| `design` | **до кода**, на предложении | specs + rubric + architecture (см. ниже) | 3 |
|
||
|
||
**Состав сверяется по этой таблице до коммита.** Реестр из трёх-восьми пунктов
|
||
проверяется взглядом — и это единственная защита от промаха, который уже
|
||
случился: пропуск прохода **не отличим от прохода без находок** (гейт зелёный,
|
||
спеки сошлись, отчёт выглядит полным), а заметить его мог бы только триаж,
|
||
который сам заполняется тем, что ему подали. Отчёт обязан перечислять запущенные
|
||
проходы **поимённо и с исходом**; непущенный идёт строкой «не запускался» в
|
||
границы покрытия, а не отсутствует. Цена молчащего пропуска измерена: семь
|
||
находок и отдельная задача на их дозакрытие.
|
||
|
||
Правило выбора профиля — **по факту изменения, не по ощущению важности**:
|
||
|
||
- есть миграция схемы, новый пакет, изменение публичного контракта (API,
|
||
протокол, формат на диске) или трогается правило, определяющее идентичность и
|
||
слияние данных → `deep`;
|
||
- иначе меняется поведение, видимое снаружи (эндпоинт, форма ответа, код ответа,
|
||
формат лога) → `standard`;
|
||
- иначе → `quick`.
|
||
|
||
Что именно в этом проекте считается публичным контрактом и какие пути означают
|
||
`deep` — раздел `## Триггеры` брифа. Он **уточняет** правило, а не отменяет его:
|
||
если триггеров в брифе нет, работает список выше.
|
||
|
||
Профиль объявляется в отчёте. Понижение профиля — решение оркестратора, и оно
|
||
попадает в границы покрытия строкой «профиль понижен до X, потому что …».
|
||
|
||
## Режим запуска: параллельно или последовательно
|
||
|
||
Профиль отвечает «какие проходы», режим — «как их запускать». Стадии всегда идут
|
||
по порядку номеров; выбор касается только проходов **внутри** стадии.
|
||
|
||
| Режим | Как | Когда |
|
||
|---|---|---|
|
||
| **последовательно** (умолчание) | по одному, следующий стартует после отчёта предыдущего | всегда, пока не попросили иначе |
|
||
| **параллельно** | названные проходы — одним сообщением | только по явной просьбе **и** с явно названным набором |
|
||
|
||
**Умолчание — последовательно, и его не надо обосновывать.** Обосновывается
|
||
отступление.
|
||
|
||
**Параллельный режим включается при двух условиях сразу**, и второе так же
|
||
обязательно, как первое:
|
||
|
||
1. **о нём попросили явно** — «гони параллельно», а не «сделай побыстрее»;
|
||
2. **названо, что именно гнать параллельно** — поимённый набор проходов
|
||
(«`specs` и `code` параллельно») или стадия целиком («стадию 1 параллельно»).
|
||
|
||
Просьба без набора — **не основание**: гоним последовательно и одной строкой
|
||
говорим, что набор не был назван. Это не придирка к формулировке. Параллелить
|
||
можно ровно то, что не мешает друг другу, а знание об этом лежит у того, кто
|
||
просит: он видит, занята ли машина, и ждёт ли он от прогона замеров. Домысливать
|
||
набор за него — значит принять решение, которое он оставил себе.
|
||
|
||
Почему умолчание именно такое:
|
||
|
||
- **Замеры.** Проходы `adversary` и `ops` доказывают находки числами: время
|
||
удержания блокировки против её таймаута, пик кучи против размера тела, темп
|
||
роста файлов журнала, длительность транзакции. Два меряющих прохода на одной
|
||
машине соревнуются за диск, CPU и за саму СУБД и выдают числа, которые не
|
||
воспроизведутся. Это не гипотеза: правило выведено из находок, целиком
|
||
державшихся на таких замерах, — у каждого проекта они свои и лежат в разделе
|
||
`## Прецеденты` его брифа. Число, снятое под конкурентную нагрузку от соседнего
|
||
прохода, — это находка с испорченным оракулом, а её опровержение стоит дороже
|
||
всего выигрыша от параллельности.
|
||
- **Машина одна.** Рядом идёт задача, поднят сервис, гоняется гейт или дорогая
|
||
проверка проекта.
|
||
- **Ранний выход** возможен только при последовательном прогоне (см. ниже).
|
||
- **Разбор самого конвейера.** Когда выясняется, почему проход чего-то не нашёл,
|
||
порядок и изоляция важнее скорости.
|
||
|
||
Если параллельный режим всё же включён, в границы покрытия идёт строка: какие
|
||
проходы шли разом и что замеры, снятые в этом прогоне, как оракул слабее.
|
||
|
||
**Чего режим не меняет — и это не подлежит обсуждению.** Проход **не видит**
|
||
находок других проходов ни в каком режиме. «Последовательно» значит «по
|
||
очереди», а не «следующий читает предыдущего». Вся ценность конвейера держится
|
||
на декорреляции: под всеми ролями одна модель с одними априорными, и стоит
|
||
показать ей чужой вывод — она согласится. Согласие нескольких проходов и так не
|
||
повышает `confidence` (см. «Честный предел»); согласие **наведённое** ещё и
|
||
маскируется под независимое подтверждение. Единственный, кто видит всё, — триаж,
|
||
и это его работа.
|
||
|
||
**Ранний выход** (последовательный режим делает его возможным — это его побочная
|
||
выгода, а не повод его выбирать). Допустимо остановить прогон, не докатив
|
||
остаток, ровно в одном случае: находка требует **переделки формы** изменения, и
|
||
остальные проходы будут смотреть на код, которого через час не станет. Тогда:
|
||
|
||
- прогон останавливается, находка чинится, конвейер запускается **заново с
|
||
нулевой стадии** — а не «доезжает» остатком по старому коду;
|
||
- незапущенные проходы идут в границы покрытия строкой «не запускался: прогон
|
||
остановлен на <проход> из-за <находка>», поимённо;
|
||
- триаж запускается только на полном прогоне. Отчёт триажа по половине проходов
|
||
выглядит полным, потому что агрегирует всё, что ему подали, — это тот же
|
||
молчащий пропуск, что и в разделе «Профили».
|
||
|
||
Ранний выход по находке, которая чинится в пределах существующей формы
|
||
(`Действие: инлайн`), **не делается**: дешевле дособрать все находки и починить
|
||
пачкой, чем гонять конвейер дважды.
|
||
|
||
Режим объявляется в отчёте наравне с профилем, и если он **параллельный** — с
|
||
причиной и составом. Последовательный объявляется одним словом.
|
||
|
||
## Стадия 0 — Gate (обязательна во всех профилях)
|
||
|
||
Агент `review-gate`. Запускает команду гейта из раздела `## Гейт` брифа и
|
||
интерпретирует вывод.
|
||
|
||
**Пока гейт красный — опиниативные проходы не запускаются.** Оркестратор чинит и
|
||
перезапускает гейт. Исключение одно: отказ, унаследованный от базовой ветки
|
||
(гейт проверяет это прогоном на базе) — тогда он фиксируется находкой и не
|
||
блокирует.
|
||
|
||
Гейт возвращает не только «зелено/красно», но и находки класса **отсутствующая
|
||
верификация**: изменённые строки без покрытия, конкурентность без теста с
|
||
параллельным доступом, флаки-тест (не ниже `major`), недоступный инструмент.
|
||
|
||
Шаги выбираются по изменённым файлам: правка документации не гоняет тесты,
|
||
линтеры и детектор гонок. Пропуск при этом не молчит — он виден в сводке с
|
||
причиной и уезжает в границы покрытия, как и любой другой `SKIP`.
|
||
|
||
Шаги, которые красят гейт безусловно, перечислены в брифе с причиной. Проходу
|
||
запрещено списывать такой отказ в мелочь.
|
||
|
||
## Стадия 1 — Conformance (обязательна во всех профилях)
|
||
|
||
Два applicative-прохода: оба применяют **записанный** критерий, оба дешёвые.
|
||
Замеров они не делают и потому безобиднее прочих, если параллельный режим
|
||
попросят с их именами; сами по себе идут по очереди, как и все.
|
||
|
||
- `review-specs` — критерий взят из **дельта-спек предлагаемого изменения**, а не
|
||
из proposal, сообщения коммита или описания задачи. Сверка двунаправленная;
|
||
направление `code → spec` важнее.
|
||
- `review-code` — критерий взят из конвенций проекта: файла или каталога файлов,
|
||
путь — раздел `## Карта` брифа. Берётся только та их часть, которая **не
|
||
выражается правилом**:
|
||
механизируемое уже проверила стадия 0. Что именно механизировано, тот же раздел
|
||
брифа перечисляет — повторять это проходом вредно.
|
||
|
||
Recall обоих равен длине их источника — это и есть предел applicative-проходов,
|
||
ради которого существует стадия 2.
|
||
|
||
## Стадия 2 — Adversarial и operational (`standard`, `deep`)
|
||
|
||
Два прохода:
|
||
|
||
- `review-adversary` — находка есть **построенный путь**, а не свойство;
|
||
- `review-ops` — постмортем от симптома у владельца сервиса к строке кода.
|
||
|
||
**Эту пару параллелить не стоит даже по просьбе — переспроси.** Оба доказывают
|
||
находки замером, и оба меряют одно и то же железо. Запущенные разом, они портят
|
||
числа друг другу, а испорченный оракул хуже отсутствующего: находка выглядит
|
||
доказанной. Если их всё же назвали в параллельном наборе — выполняй, но скажи в
|
||
границах покрытия, что числа этого прогона сняты под соседней нагрузкой.
|
||
|
||
**Эта стадия зарабатывает больше всех остальных вместе, и потому стоит в
|
||
`standard`, а не только в `deep`.** Измерено на пяти задачах подряд: враждебный
|
||
проход дал пять из семи выживших находок дозапуска (включая обе верхние);
|
||
эксплуатационный — единственный, кто нашёл, что откат бинаря поверх новой схемы
|
||
стартует молча. Оба несут внешний оракул по построению: один обязан путь
|
||
**прогнать**, второй смотрит ось времени и эксплуатации, которую не смотрит
|
||
никто другой.
|
||
|
||
Материал обоим даёт бриф: `## Модель угроз` — враждебному, `## Прод и поток` —
|
||
эксплуатационному. Без этих разделов стадия вырождается в общие места.
|
||
|
||
## Стадия 3 — Independent reimplementation (`deep`, по триггеру)
|
||
|
||
- `review-reimpl` — пишет свою реализацию, не открывая существующую, затем
|
||
диффит по решениям. **Запускается по триггеру, а не всегда:** изменение вводит
|
||
новое правило идентичности, слияния или разбора (проектная формулировка
|
||
триггера — в разделе `## Триггеры` брифа). Это самый дорогой проход конвейера
|
||
(его счёт определяется объёмом вывода — он пишет реализацию целиком), а вне
|
||
этого триггера независимый взгляд в значительной мере уже дал профиль `design`:
|
||
код писался под его находки. Триггер выбран по факту: единственный раз, когда
|
||
триаж назвал отсутствие `reimpl` дырой покрытия, — это была задача с новым
|
||
правилом слияния сущностей.
|
||
|
||
## Стадия 4 — Global (`deep`, `design`)
|
||
|
||
Агент `review-architecture`. Получает **вход шире диффа**: дерево пакетов с
|
||
назначением, граф внутренних зависимостей, инвентарь существующих концепций.
|
||
Команду, которая это готовит, даёт раздел `## Команды` брифа; нет команды —
|
||
проход собирает карту сам и говорит об этом в границах покрытия.
|
||
|
||
Главный вопрос — концептуальная целостность и **второй способ** делать то, что
|
||
уже делается. Он же и оправдывает проход: на задаче про пересборку архитектурный
|
||
проход нашёл, что новый код был **вторым проигрывателем журнала** со своим
|
||
порядком. Второй обязательный вопрос — **что опытный человек отсюда удалил бы**:
|
||
слой с единственной реализацией, интерфейс ради мока, незапрошенная
|
||
конфигурируемость, подстраховка поверх подстраховки. Потолок — 3 находки плюс
|
||
секция «дешевле переделать до мерджа».
|
||
|
||
## Стадия 5 — Triage (обязательна)
|
||
|
||
Агент `review-triage`. Единственный, кто агрегирует. Получает сырые выводы всех
|
||
проходов, `git diff`, профиль, режим и **список запущенных проходов**; возвращает
|
||
финальный отчёт.
|
||
|
||
Без триажа проходы дают порядка сорока замечаний при единицах существенных.
|
||
Потребитель здесь — оркестратор, который **молча реализует** всё, что прочитал:
|
||
цена нетриажированного отчёта — не потерянное время человека, а разросшийся от
|
||
вкусовщины код.
|
||
|
||
Порядок: дедупликация по причине → оракул для всего `critical`/`major` →
|
||
понижение неподтверждённого до гипотезы → отсев вкусовщины → ранжирование по
|
||
ущербу × вероятности → потолок 7 пунктов в основном списке.
|
||
|
||
## Профиль `design` — до кода
|
||
|
||
Запускается на шаге ревью спек (шаг 4 скилла `av-dev-pipeline:task-pipeline`),
|
||
когда change уже
|
||
имеет `proposal.md` и дельта-спеки, но кода ещё нет. Состав:
|
||
|
||
1. `review-specs` в режиме «дизайн ДО кода»;
|
||
2. `review-rubric`, фаза 1 без фазы 2: рубрика на задуманный узел становится
|
||
приёмочными критериями и уезжает в `tasks.md`;
|
||
3. `review-architecture` на предложении: вводит ли change новое понятие, можно ли
|
||
выразить существующими — **включая конструкции стандартной библиотеки**, — не
|
||
появляется ли второй способ. Вопрос «не изобретаем ли то, что уже есть в
|
||
библиотеке» живёт здесь;
|
||
4. вопрос автору дизайна: **«предложи три формы решения и назови компромисс
|
||
каждой»** — если ответ показывает, что рассматривалась одна, это находка.
|
||
|
||
Смысл профиля: архитектурная находка на готовом коде стоит переписывания и
|
||
поэтому игнорируется; та же находка на предложении стоит абзаца обсуждения.
|
||
|
||
`rubric` живёт **только** в этом профиле. Судить код по критерию, под который он
|
||
писался, — корреляция по построению; те же 8–14 свойств уже лежат приёмочными
|
||
критериями в `tasks.md`.
|
||
|
||
## Контракт находок
|
||
|
||
Единый для всех проходов — [references/finding-contract.md](references/finding-contract.md).
|
||
Коротко: заголовок через **последствие**, обязательные поля `Файл`, `Severity`,
|
||
`Confidence`, `Оракул`, `Последствие`, `Предложение`, `Найдено проходом`.
|
||
`critical` без оракула или построенного пути не существует. Находка без поля
|
||
«Последствие» не выводится вовсе.
|
||
|
||
Каждый проход завершает вывод блоком `## Coverage of this pass`.
|
||
|
||
## Что происходит с находками дальше
|
||
|
||
- Оркестратор чинит помеченное `Действие: инлайн` и **не логирует мелочь**.
|
||
- `Действие: развилка` — вопросом с вариантами и ценой каждого туда, где проект
|
||
держит вопросы (это знает вызвавший пайплайн, а не конвейер). Оркестратор не
|
||
останавливается: он урезает изменение до остатка и доводит его.
|
||
- Находка не для этого мерджа, но реальная (отложенный `major`, развилка,
|
||
решённая «потом»), — не теряется, но **и не заводится здесь**. Конвейер отдаёт
|
||
её **списком урожая** в отчёте: формулировка, оракул, провенанс (какой проход,
|
||
какой change). Заведение задач принадлежит тому, кто ведёт задачи проекта, —
|
||
у него свой формат, своя нарезка и свои правила дублей. Мелочь класса `nit`
|
||
идёт в урожай одной пачкой, а не записью на находку.
|
||
- `Promote candidates` — по процедуре [references/promote.md](references/promote.md):
|
||
находка → конвенция → правило линтера → **удаление из конвенций и из брифа**.
|
||
Третий шаг обязателен.
|
||
- Дефект, проскочивший ревью и всплывший позже, идёт в журнал проекта
|
||
([references/review-journal.md](references/review-journal.md)) — сразу, не
|
||
ретроспективно: теряется именно причина непоймания.
|
||
- **Отчёт триажа сохраняется вместе с изменением** (например, в
|
||
`openspec/changes/<id>/review/`). Он единственное, по чему потом видно, что
|
||
было найдено и что из этого не заведено: нулевой урожай при непустом отчёте
|
||
виден сразу.
|
||
|
||
## Честный предел
|
||
|
||
Модель воспроизводит медиану публичного кода, смещённую к популярному и
|
||
туториальному: отсюда тяга к интерфейсам ради интерфейсов, лишним мокам и
|
||
конфигурируемости, которую никто не просил. **«Идиоматично» и «распространено» —
|
||
разные вещи**; проходы обязаны различать их и опираться на поимённое положение
|
||
гайда, а не на ощущение частотности.
|
||
|
||
Согласие нескольких проходов — **не подтверждение**: это один источник,
|
||
высказавшийся несколько раз. Совпадение повышает приоритет, но не `confidence`.
|
||
|
||
Что недоступно **этому** проекту принципиально — перечисляет раздел
|
||
`## Недоступно проверке` брифа, и он целиком уезжает в границы покрытия.
|
||
Независимо от проекта недоступно:
|
||
|
||
- поведение внешних систем в их будущих версиях;
|
||
- реальный профиль нагрузки и то, что на самом деле лежит в данных;
|
||
- завязка внешних потребителей на текущую форму ответа;
|
||
- суждение «этой функциональности не должно существовать».
|
||
|
||
Отдельно и честно: **поимённая сверка с положениями стайлгайдов языка не
|
||
задаётся ни одним проходом.** Проход про идиоматичность упразднён, его способные
|
||
части переселены (эксперимент против поведения библиотеки и драйвера — в `ops`,
|
||
вопрос 8; «не изобретаем ли то, что уже есть в библиотеке» — в `architecture`,
|
||
вопрос 1), но различение «идиоматично против распространено» теперь не спрашивает
|
||
никто. Класс обратимый — портит форму кода, не данные, — и его надо признавать в
|
||
границах покрытия, а не считать проверенным.
|
||
|
||
Это и есть причина, по которой конвейер готовит ревью, а не заменяет его.
|
||
|
||
## Ссылки
|
||
|
||
- Skill `av-dev-pipeline:project-brief` — заведение и обновление брифа.
|
||
- [references/project-brief.md](references/project-brief.md) — контракт брифа проекта.
|
||
- [references/brief-template.md](references/brief-template.md) — шаблон брифа.
|
||
- [references/finding-contract.md](references/finding-contract.md) — контракт находок.
|
||
- [references/promote.md](references/promote.md) — промоут находка → конвенция → правило → удаление.
|
||
- [references/calibration.md](references/calibration.md) — калибровка инъекцией, вердикты keep/retune/drop.
|
||
- [references/review-journal.md](references/review-journal.md) — журнал проскочивших дефектов.
|