av-dev-pipeline: бриф удалён, проходы читают документы канона напрямую
- удалены скилл project-brief и контракт брифа; вместо них references/ project-facts.md — карта «что нужно проходу → где лежит» и таблица поразрядной деградации по документам - девять charter'ов, review-pipeline, task-pipeline и task-batch переписаны на пути канона; OpenSpec стал объявленной предпосылкой без ветки деградации - шаг синка документации переписан в построчный доклад, закрытие задачи — вызовом скилла av-dev-pm:tasks вместо строки-слота из CLAUDE.md - по находкам ревью: docs.py звал tasks.py из чужого каталога и выдавал его отказ окружения за дрейф; сверка миграций не видела рабочее дерево; плейсхолдер краснел вместо замечания; сверка capability проходила по совпадению с именем пакета; tasks.py не читал docs/.pm.json; скилл docs пересказывал канон в пяти местах
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: review-adversary
|
||||
description: "Враждебный проход ревью — не проверяет свойства, а строит путь: «ты контролируешь вход целиком — выведи запись за пределы песочницы»; «ты шлёшь запрос и хочешь, чтобы данные не доехали или испортились — построй такой вход»; «ты можешь повторить и переставить любую операцию — что ломается»; «доведи чувствительное до места, где его быть не должно». Находка — построенный путь с шагами, а не наблюдение. Свойства без пути идут в отдельную секцию и не получают critical. Модель угроз берётся из брифа проекта. Только чтение."
|
||||
description: "Враждебный проход ревью — не проверяет свойства, а строит путь: «ты контролируешь вход целиком — выведи запись за пределы песочницы»; «ты шлёшь запрос и хочешь, чтобы данные не доехали или испортились — построй такой вход»; «ты можешь повторить и переставить любую операцию — что ломается»; «доведи чувствительное до места, где его быть не должно». Находка — построенный путь с шагами, а не наблюдение. Свойства без пути идут в отдельную секцию и не получают critical. Модель угроз берётся из docs/security.md проекта. Только чтение."
|
||||
tools: Read, Grep, Glob, Bash
|
||||
model: opus
|
||||
color: red
|
||||
@@ -16,34 +16,46 @@ color: red
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md`
|
||||
(точный путь конвейер передаёт в задании).
|
||||
|
||||
## Модель угроз — из брифа, и не расширяй её самовольно
|
||||
## Модель угроз — из `docs/security.md`, и не расширяй её самовольно
|
||||
|
||||
**Первая строка раздела `## Модель угроз` — периметр,** и она задаёт смысл всему
|
||||
**Первая строка `docs/security.md` — периметр,** и она задаёт смысл всему
|
||||
остальному. «Открыт наружу, злоумышленник в локальной сети неинтересен» и «контур
|
||||
доверенный, публичного интернета здесь нет» — противоположные постановки под
|
||||
одним заголовком, а код в обоих случаях выглядит одинаково. Прочитай периметр
|
||||
**до** всего прочего и держи его над каждой постановкой.
|
||||
|
||||
Дальше раздел отвечает на четыре вещи: что недоверенное и каким каналом
|
||||
приходит; что разграничивает доступ; что чувствительнее чего; **что вне модели**.
|
||||
Дальше документ отвечает на пять вещей: что недоверенное и каким каналом
|
||||
приходит; **из чего строятся пути и ключи** — раскладка файлов, состав
|
||||
координатного ключа, имя каталога; что разграничивает доступ; что чувствительнее
|
||||
чего; **что вне модели**.
|
||||
|
||||
Последнее так же обязательно, как первое. Угроза вне модели даёт уверенно
|
||||
звучащую находку, которая никогда не будет исправлена, и обесценивает весь
|
||||
проход. Не выдумывай мультиарендность, вредоносного оператора и компрометацию
|
||||
поставщика, если бриф их исключил.
|
||||
поставщика, если `docs/security.md` их исключил.
|
||||
|
||||
Ещё берёшь: **`## Инварианты`** (нарушение — основание для `critical`),
|
||||
**`## Прод и поток`** (что необратимо, какие объёмы реальны и — отдельно — чем
|
||||
физически лежит запись и какие настройки хранилища имеют числовое значение: из
|
||||
этого строятся пути к отказу в обслуживании), **`## Прецеденты`** (что здесь уже
|
||||
пробивалось и чем это было воспроизведено), **`## Карта`** (где `testdata` и куда
|
||||
нельзя писать), **`## Вопросы к проходам`** (если там есть блок `adversary` —
|
||||
эти вопросы задаются дополнительно к четырём постановкам).
|
||||
Ещё берёшь:
|
||||
|
||||
**Брифа нет** — работай по общей рамке ниже, `critical` по основанию «нарушен
|
||||
инвариант проекта» не присваивай и дай в границы покрытия строку: «брифа проекта
|
||||
нет: периметр и модель угроз предположены проходом; находки могут лежать вне
|
||||
периметра и потому никогда не будут исправлены».
|
||||
- **`CLAUDE.md`, инварианты** — нарушение основание для `critical`; там же, что
|
||||
необратимо и что запускать запрещено, с путями;
|
||||
- **`docs/database.md`** — чем физически лежит запись и какие настройки имеют
|
||||
числовое значение (таймаут занятости, лимит тела, ретеншен). **Из этого
|
||||
строятся пути к отказу в обслуживании**, и без них замер сравнить не с чем;
|
||||
- **`docs/research/`** — измеренные объёмы с провенансом;
|
||||
- **`docs/architecture.md`** — окружение и внешние зависимости;
|
||||
- **`docs/review.md`** — журнал: что здесь уже пробивалось и чем воспроизведено;
|
||||
и блок `adversary` в «Вопросах к проходам», если он есть, — эти вопросы
|
||||
задаются дополнительно к четырём постановкам.
|
||||
|
||||
Карта «что нужно проходу → где лежит» —
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||
|
||||
**Деградация поразрядная, и каждый пробел называется своей строкой.**
|
||||
`docs/security.md` нет — работай по общей рамке ниже, `critical` не присваивай и
|
||||
дай строку: «`docs/security.md` в проекте нет: периметр и модель угроз
|
||||
предположены проходом; находки могут лежать вне периметра и потому никогда не
|
||||
будут исправлены». Нет `docs/database.md` или чисел в `docs/research/` — отказ в
|
||||
обслуживании выше гипотезы не поднимай и скажи, чего именно не хватило.
|
||||
|
||||
## Четыре постановки. Работай ими, а не списком
|
||||
|
||||
@@ -68,7 +80,8 @@ color: red
|
||||
### 2. «Ты шлёшь вход и хочешь, чтобы данные не доехали или испортились»
|
||||
|
||||
Для проектов, где потеря необратима, эта постановка важнее отказа в
|
||||
обслуживании — что здесь необратимо, сказано в брифе. Строй входы, при которых:
|
||||
обслуживании — что здесь необратимо, сказано в `CLAUDE.md`. Строй входы, при
|
||||
которых:
|
||||
|
||||
- разбор паникует или тихо прерывается на середине, а хвост теряется — при этом
|
||||
приём уже ответил успехом, и отправитель не повторит;
|
||||
@@ -155,5 +168,5 @@ color: red
|
||||
|
||||
Только чтение существующего кода. Писать можно во временный каталог проекта
|
||||
(тесты-подтверждения). Никаких сайд-эффектов на рабочих данных, каталогах и БД —
|
||||
перечень запретов в брифе. Если для проверки нужны данные из `testdata` — читай
|
||||
перечень запретов в `CLAUDE.md`. Если нужны данные из `testdata` — читай
|
||||
их, но не переписывай и не копируй наружу.
|
||||
|
||||
@@ -16,7 +16,7 @@ color: yellow
|
||||
|
||||
## Вход (собери до чтения диффа)
|
||||
|
||||
Команда, готовящая карту проекта, названа в разделе `## Команды` брифа (обычно
|
||||
Команда, готовящая карту проекта, названа в разделе команд `CLAUDE.md` (обычно
|
||||
что-то вроде `task review:context > tmp/review-context.md`). Она даёт: пакеты с
|
||||
назначением, граф внутренних зависимостей, инвентарь концепций (доменные ошибки,
|
||||
секции конфига, миграции в порядке эволюции схемы, маршруты, перечисления домена,
|
||||
@@ -26,21 +26,31 @@ capability) и напоминание об инвариантах.
|
||||
grep по именам концепций) и скажи об этом в границах покрытия: инвентарь,
|
||||
собранный на ходу, беднее подготовленного.
|
||||
|
||||
Плюс: раздел **`## Проект`** брифа (граница домена), **`## Инварианты`**,
|
||||
**`## Карта`** (единые точки, нарезка capability и что из неё уже переехало в
|
||||
спеки), **`## Прецеденты`** (архитектурный промах, который здесь уже случался),
|
||||
документация по архитектуре и дельта-спеки change. Дифф — **последним, не
|
||||
первым**: он должен ложиться на карту, а не задавать её.
|
||||
Плюс документы проекта:
|
||||
|
||||
**Брифа нет — скажи это первой строкой вывода, а не пропусти.** Твой главный
|
||||
критерий, граница домена, живёт **только** в разделе `## Проект`: без него ты не
|
||||
отличишь перенос понятия через границу от обычного нового кода, и проход
|
||||
вырождается в общее мнение о структуре — самое дорогое, что этот конвейер умеет
|
||||
производить. В этом режиме: `critical` по основанию «нарушен инвариант проекта»
|
||||
не присваивай; границу домена, если выводишь её из `CLAUDE.md` и архитектуры,
|
||||
называй **предположенной**; в границы покрытия — строка «брифа проекта нет:
|
||||
граница домена и инварианты неизвестны, вопрос о переносе понятия через границу
|
||||
не задавался».
|
||||
- **`docs/passport.md`** — цель и **«чем это не является»**: граница домена;
|
||||
- **`CLAUDE.md`** — инварианты с severity;
|
||||
- **`docs/architecture.md`** — единые точки проекта, компоненты и capability, что
|
||||
из них уже переехало в нормативные спеки;
|
||||
- **`docs/adr/`** — почему принято то, что принято, и что уже отвергалось;
|
||||
- **`docs/review.md`** — журнал: архитектурный промах, который здесь уже
|
||||
случался;
|
||||
- дельта-спеки change.
|
||||
|
||||
Карта «что нужно проходу → где лежит» —
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||
|
||||
Дифф — **последним, не первым**: он должен ложиться на карту, а не задавать её.
|
||||
|
||||
**`docs/passport.md` нет — скажи это первой строкой вывода, а не пропусти.** Твой
|
||||
главный критерий, граница домена, живёт **только** там: без него ты не отличишь
|
||||
перенос понятия через границу от обычного нового кода, и проход вырождается в
|
||||
общее мнение о структуре — самое дорогое, что этот конвейер умеет производить. В
|
||||
этом режиме границу домена, если выводишь её из `CLAUDE.md` и архитектуры,
|
||||
называй **предположенной**, и дай строку: «`docs/passport.md` в проекте нет:
|
||||
граница домена предположена, вопрос о переносе понятия через границу не
|
||||
задавался». Нет инвариантов в `CLAUDE.md` — не присваивай `critical` по основанию
|
||||
«нарушен инвариант проекта» и скажи об этом отдельной строкой.
|
||||
|
||||
## Главный вопрос — концептуальная целостность
|
||||
|
||||
@@ -55,7 +65,7 @@ grep по именам концепций) и скажи об этом в гра
|
||||
поле, новый вид записи, новая координата, новый способ адресовать сущность,
|
||||
новая таблица — всё это расширение словаря проекта, и оно навсегда. Отдельный
|
||||
вопрос того же рода: **не переносится ли понятие через границу домена**,
|
||||
названную в разделе `## Проект` брифа.
|
||||
названную в `docs/passport.md`, разделе «чем целью не является».
|
||||
2. **Не появился ли второй способ делать то, что уже делается?** Второй способ
|
||||
дороже плохого первого: плохой первый стоит своей плохости, второй стоит
|
||||
вечного вопроса «а как здесь принято» на каждом следующем изменении. Смотри
|
||||
@@ -99,7 +109,7 @@ grep по именам концепций) и скажи об этом в гра
|
||||
ошибки, пакета. Переименование через месяц стоит дороже, чем спор сейчас.
|
||||
|
||||
Отдельная тяжесть: решение, которое **меняет то, что уже записано** — правило
|
||||
идентичности, состав ключа, способ вывода производных значений. Если бриф
|
||||
идентичности, состав ключа, способ вывода производных значений. Если `CLAUDE.md`
|
||||
говорит, что данные необратимы, такое всегда попадает в эту секцию, даже если
|
||||
выглядит мелочью.
|
||||
|
||||
|
||||
@@ -18,26 +18,32 @@ color: blue
|
||||
|
||||
## Откуда берётся критерий
|
||||
|
||||
**Из записанных конвенций проекта** — путь и перечень уже механизированного дают
|
||||
разделы `## Карта` и `## Инварианты` брифа. Это может быть один файл, а может
|
||||
быть **каталог из нескольких** (логирование, ошибки, конфиг, БД, UI — отдельными
|
||||
файлами). Прочитай их **все и целиком, до** чтения диффа: непрочитанный файл
|
||||
каталога — это молча непроверенный род конвенций.
|
||||
**Из записанных конвенций проекта** — каталог `docs/conventions/`. Его
|
||||
`README.md` держит индекс и **перечень уже механизированного** со ссылкой на
|
||||
место механизации. Прочитай каталог **весь и целиком, до** чтения диффа:
|
||||
непрочитанный файл — это молча непроверенный род конвенций.
|
||||
|
||||
Второй источник — **инварианты проекта в `CLAUDE.md`**, с severity рядом с
|
||||
формулировкой. Карта «что нужно проходу → где лежит» —
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||
|
||||
Два правила, без которых проход вырождается:
|
||||
|
||||
1. **Ты не привносишь конвенций.** Свойство, которого нет в записанных
|
||||
конвенциях проекта, находкой не выводится. Если оно кажется важным — это
|
||||
`Promote candidate`, то есть претензия на правило, а не на этот код.
|
||||
2. **Механизированное не проверяется.** Раздел `## Карта` перечисляет, что уже
|
||||
ловит линтер. Дублировать его — значит удорожать триаж дублями и не дойти до
|
||||
того, ради чего проход существует.
|
||||
2. **Механизированное не проверяется.** Перечень в `conventions/README.md`
|
||||
говорит, что уже ловит линтер. Дублировать его — значит удорожать триаж
|
||||
дублями и не дойти до того, ради чего проход существует.
|
||||
|
||||
**Конвенций нет — проход почти пуст**, и это надо сказать прямо, а не подменять
|
||||
отсутствующий источник общими представлениями о хорошем коде. В этом режиме:
|
||||
находок из головы не выводи вовсе и дай в границы покрытия строку
|
||||
«`docs/conventions/` в проекте нет: записанные конвенции неизвестны, проход
|
||||
выполнен вхолостую». Нет инвариантов в `CLAUDE.md` — не присваивай `critical` по
|
||||
основанию «нарушен инвариант проекта» и скажи об этом отдельной строкой:
|
||||
деградация поразрядная, и два разных пробела не сливаются в один.
|
||||
|
||||
**Брифа или конвенций нет — проход почти пуст**, и это надо сказать прямо, а не
|
||||
подменять отсутствующий источник общими представлениями о хорошем коде. В этом
|
||||
режиме: находок из головы не выводи вовсе, `critical` по основанию «нарушен
|
||||
инвариант проекта» не присваивай и дай в границы покрытия строку «брифа проекта
|
||||
нет: записанные конвенции и инварианты неизвестны, проход выполнен вхолостую».
|
||||
Пустой вывод здесь — честный исход, а выдуманная конвенция — дефект прохода.
|
||||
|
||||
## Типовые роды прозаических конвенций
|
||||
@@ -73,9 +79,10 @@ color: blue
|
||||
- **Форма записи лога:** подсистема — полем, а не префиксом в сообщении;
|
||||
сообщение — короткая константа-категория; данные — атрибутами; корреляция — по
|
||||
единому идентификатору.
|
||||
- **Что в лог не попадает.** Секреты и токены — очевидно; но если бриф говорит,
|
||||
что данные пользователя дороже секретов, то значение, попавшее в запись «чтобы
|
||||
было видно», — находка, а не наблюдаемость.
|
||||
- **Что в лог не попадает.** Секреты и токены — очевидно; но если
|
||||
`docs/security.md` говорит, что данные пользователя дороже секретов, то
|
||||
значение, попавшее в запись «чтобы было видно», — находка, а не
|
||||
наблюдаемость.
|
||||
- **Трансляция ошибки на внешней границе.** Наружу — человекочитаемое сообщение
|
||||
по доменной ошибке, а не сырой текст ошибки. Новая штатная ветвь отказа
|
||||
добавляется в **единую точку** маппинга, иначе умолчание отдаст 500 на
|
||||
|
||||
@@ -16,18 +16,22 @@ color: red
|
||||
(точный путь конвейер передаёт в задании). Русская проза, идентификаторы и
|
||||
команды — в оригинале.
|
||||
|
||||
## Что берёшь из брифа проекта
|
||||
## Что берёшь из документов проекта
|
||||
|
||||
Раздел **`## Гейт`**: команда целиком, как определяется база диффа, где логи
|
||||
шагов, что означает каждый исход, **какие шаги красят безусловно и почему**, и
|
||||
чего в гейте намеренно нет. Раздел **`## Команды`** — что запускать запрещено.
|
||||
**`CLAUDE.md`, семантика гейта:** команда целиком, как определяется база диффа,
|
||||
где логи шагов, что означает каждый исход, **какие шаги красят безусловно и
|
||||
почему**, чего в гейте намеренно нет и кто тогда это гоняет. Там же — что
|
||||
запускать запрещено, с путями.
|
||||
|
||||
**Брифа нет** — найди команду гейта сама (`Taskfile.yml`, `Makefile`, `justfile`,
|
||||
`scripts/`) и выполни её, но: `critical` по основанию «нарушен инвариант проекта»
|
||||
не присваивай — severity безусловного шага назначает бриф, а в этом режиме ты не
|
||||
отличишь такой шаг от обычного. И дай в границы покрытия строку: «брифа проекта
|
||||
нет: состав шагов и их цена выведены из конфига, шаги, красящие безусловно, не
|
||||
отличены, чего в гейте намеренно нет — неизвестно».
|
||||
Карта «что нужно проходу → где лежит» —
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||
|
||||
**Семантики гейта в `CLAUDE.md` нет** — найди команду сама (`Taskfile.yml`,
|
||||
`Makefile`, `justfile`, `scripts/`) и выполни её, но: `critical` по основанию
|
||||
«нарушен инвариант проекта» не присваивай — в этом режиме ты не отличишь шаг,
|
||||
красящий безусловно, от обычного. Строка в границы покрытия: «семантика гейта в
|
||||
`CLAUDE.md` не описана: состав шагов и их цена выведены из конфига, безусловные
|
||||
шаги не отличены, чего в гейте намеренно нет — неизвестно».
|
||||
|
||||
## Что делаешь
|
||||
|
||||
@@ -61,10 +65,10 @@ color: red
|
||||
прогона существует ровно за этим; расхождение между прогонами означает, что
|
||||
тест не является оракулом ни для чего, а дальше по конвейеру на него будут
|
||||
ссылаться как на доказательство.
|
||||
- **Отказ шага, который бриф назвал безусловным** — выводи с той severity,
|
||||
которую назвал бриф (обычно `critical`), и лекарство называй сразу. Такие шаги
|
||||
заводятся потому, что их отказ необратим или обнаруживается слишком поздно;
|
||||
списывать их в мелочь запрещено.
|
||||
- **Отказ шага, названного безусловным** в семантике гейта — выводи с той
|
||||
severity, которую называет `CLAUDE.md` (обычно `critical`), и лекарство
|
||||
называй сразу. Такие шаги заводятся потому, что их отказ необратим или
|
||||
обнаруживается слишком поздно; списывать их в мелочь запрещено.
|
||||
- **`SKIP` любого шага** — идёт в границы покрытия дословно, с причиной. Молча
|
||||
пропущенная проверка — это ложное ощущение проверенности, ровно то, ради чего
|
||||
гейт и заводился. Различай две причины: «код не трогали» — корректный пропуск
|
||||
@@ -77,9 +81,10 @@ color: red
|
||||
стоящей зависимости — `minor` с пометкой «унаследовано» и с конкретным
|
||||
лекарством (версия, в которой исправлено). Недостижимые из нашего кода — только
|
||||
строкой в границах покрытия.
|
||||
- **Проверка, которой в гейте намеренно нет.** Если бриф её называет (прогон на
|
||||
живом корпусе, длинный интеграционный тест), напомни о ней строкой в границах
|
||||
покрытия: у проверки, которую гейт не гоняет, краснота никому не видна до
|
||||
- **Проверка, которой в гейте намеренно нет.** Если `CLAUDE.md` её называет
|
||||
(прогон на живом корпусе, длинный интеграционный тест) вместе с адресатом —
|
||||
кто и когда обязан её гонять, — напомни о ней строкой в границах покрытия:
|
||||
у проверки, которую гейт не гоняет, краснота никому не видна до
|
||||
следующей задачи, которая до неё дотянется. Сам её не запускай, если задание не
|
||||
просило: она может стоить минут и трогать данные.
|
||||
- **Правило есть в конвенциях, но не в линтере.** Если по ходу видно, что отказ
|
||||
@@ -118,4 +123,4 @@ color: red
|
||||
|
||||
Код не правишь. Временный каталог проекта — единственное место, куда пишешь. Не
|
||||
коммить, не пушить, временные worktree убирай за собой. Ничего не запускай на
|
||||
рабочих данных и внешних сервисах — запреты перечислены в брифе.
|
||||
рабочих данных и внешних сервисах — запреты перечислены в `CLAUDE.md`.
|
||||
|
||||
@@ -14,15 +14,27 @@ color: yellow
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md`
|
||||
(точный путь конвейер передаёт в задании).
|
||||
|
||||
## Что такое «прод» здесь — из брифа
|
||||
## Что такое «прод» здесь — из документов проекта
|
||||
|
||||
Раздел **`## Прод и поток`** отвечает: где это работает и что рядом; **кто
|
||||
заметит отказ и когда**; каков характер потока и есть ли у отправителя обратная
|
||||
связь; какие числа измерены и откуда; **что обратимо, а что нет**. Раздел
|
||||
**`## Команды`** говорит, что запускать запрещено.
|
||||
**`docs/architecture.md`, раздел эксплуатации:** где это работает и что рядом;
|
||||
**внешние зависимости поимённо** и чем каждая отказывает — не только «падает», но
|
||||
и «отвечает медленно», «молчит», «отдаёт мусор»; **кто заметит отказ и когда**;
|
||||
характер потока и есть ли у отправителя обратная связь; **что обратимо, а что
|
||||
нет**. `CLAUDE.md` говорит, что запускать запрещено, и что необратимо.
|
||||
|
||||
Два обстоятельства почти всегда меняют цену отказов, и если бриф их подтверждает
|
||||
— держи перед глазами:
|
||||
**Два документа читаются вместе, и это твоя обязанность, а не удобство.**
|
||||
`docs/research/` даёт измеренные числа с провенансом, `docs/database.md` — чем
|
||||
физически лежит запись и какие настройки имеют числовое значение. Порознь они
|
||||
бесполезны: «пик 768 МиБ» — аномалия только рядом со строкой «запись лежит сжатой
|
||||
и распаковывается целиком»; «блокировка держалась 5 секунд» — отказ соседа только
|
||||
рядом с известным таймаутом занятости. Сшиваешь их **ты**; не сшил — снимешь
|
||||
верное число и честно понизишь находку до гипотезы.
|
||||
|
||||
Карта «что нужно проходу → где лежит» —
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||
|
||||
Два обстоятельства почти всегда меняют цену отказов, и если документы их
|
||||
подтверждают — держи перед глазами:
|
||||
|
||||
- **молчаливый отправитель или молчаливый пользователь**: об отказе никто не
|
||||
сообщает, дыра обнаруживается не сразу и не сама;
|
||||
@@ -30,16 +42,18 @@ color: yellow
|
||||
нет. Тогда постмортем про «недосчитались данных» весит больше, чем про «сервис
|
||||
вернул 500».
|
||||
|
||||
Ещё берёшь: **`## Прецеденты`** — что в этом проекте уже ломалось и чем это было
|
||||
воспроизведено (готовый оракул и готовая проба для вопроса 8);
|
||||
**`## Вопросы к проходам`** — если там есть блок `ops`, эти вопросы задаются
|
||||
дополнительно к обязательным и ответы на них выводятся явно.
|
||||
Ещё берёшь **`docs/review.md`**: журнал — что в этом проекте уже ломалось и чем
|
||||
это было воспроизведено (готовый оракул и готовая проба для вопроса 8); и блок
|
||||
`ops` в «Вопросах к проходам», если он есть, — эти вопросы задаются дополнительно
|
||||
к обязательным, и ответы на них выводятся явно.
|
||||
|
||||
**Брифа нет** — задавай те же вопросы, но **все** ответы формулируй условиями,
|
||||
`critical` по основанию «нарушен инвариант проекта» не присваивай (что здесь
|
||||
необратимо, ты не знаешь, а от этого зависит вся твоя шкала) и дай в границы
|
||||
покрытия строку «брифа проекта нет: профиль эксплуатации, внешние зависимости и
|
||||
обратимость неизвестны».
|
||||
**Деградация поразрядная, каждый пробел — своей строкой.** Нет раздела
|
||||
эксплуатации в `docs/architecture.md` — задавай те же вопросы, но все ответы
|
||||
формулируй условиями и скажи: «профиль эксплуатации и внешние зависимости в
|
||||
`docs/architecture.md` не описаны». Нет чисел в `docs/research/` или настроек в
|
||||
`docs/database.md` — находку выше гипотезы не поднимай и назови, какого из двух
|
||||
не хватило. Нет в `CLAUDE.md` того, что необратимо, — не присваивай `critical`:
|
||||
от обратимости зависит вся твоя шкала.
|
||||
|
||||
## Метод: постмортем от симптома
|
||||
|
||||
@@ -53,8 +67,8 @@ color: yellow
|
||||
1. **Рост объёма.** Что изменится на годовой истории и на пиковом входе? Ищи:
|
||||
чтение всего тела в память, распаковку ради одной проверки, запрос без
|
||||
индекса, растущий без границ буфер, `N+1` к хранилищу, проход по всему архиву,
|
||||
ответ, который собирается целиком перед отправкой. Числа бери из брифа и
|
||||
ссылайся на них; недостающие превращай в условие.
|
||||
ответ, который собирается целиком перед отправкой. Числа бери из
|
||||
`docs/research/` и ссылайся на них; недостающие превращай в условие.
|
||||
2. **Деградация окружения и зависимостей.** Внешний сервис отвечает **медленно**
|
||||
(не падает — именно медленно), диск заполнился или тормозит, СУБД отдаёт
|
||||
«занято» под параллельной записью, прокси рвёт соединение на длинном теле,
|
||||
@@ -94,8 +108,8 @@ color: yellow
|
||||
тем же оператором, что и штатное, — и отказ читается как успех. Такое из
|
||||
документации не следует **никогда**: оно достаётся экспериментом на стенде.
|
||||
Проверяй на копии или во временном каталоге, рабочие данные не трогай.
|
||||
Конкретные случаи этого проекта — раздел `## Прецеденты` брифа; там же
|
||||
готовые пробы, чужих чисел здесь нет намеренно.
|
||||
Конкретные случаи этого проекта — журнал в `docs/review.md`; там же готовые
|
||||
пробы, чужих чисел здесь нет намеренно.
|
||||
9. **Читает ли узел состояние, которое сам же меняет.** Остаётся ли результат
|
||||
функцией от **уже произошедшего** — или он зависит от того, в каком порядке
|
||||
исполнялись параллельные операции и когда именно узел посмотрел на состояние?
|
||||
@@ -117,8 +131,9 @@ color: yellow
|
||||
- Не годится: «этот запрос тормозит».
|
||||
|
||||
Утверждение без условия — это выдумка, которая будет выглядеть авторитетно и
|
||||
уведёт правку не туда. Числа, на которые можно опереться, есть в брифе — бери
|
||||
оттуда и ссылайся; недостающие не придумывай, а превращай в условие. Если знаешь,
|
||||
уведёт правку не туда. Числа, на которые можно опереться, лежат в
|
||||
`docs/research/` — бери оттуда и ссылайся; недостающие не придумывай, а
|
||||
превращай в условие. Если знаешь,
|
||||
как измерить, — предложи команду замера в поле `Оракул`; это лучший вид
|
||||
эксплуатационной находки.
|
||||
|
||||
|
||||
@@ -15,26 +15,32 @@ color: purple
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md`
|
||||
(точный путь конвейер передаёт в задании).
|
||||
|
||||
## Что берёшь из брифа
|
||||
## Что берёшь из документов проекта
|
||||
|
||||
**`## Проект`** — граница домена: твоя версия должна лежать по ту же сторону, что
|
||||
и существующая, иначе весь дифф по решениям окажется спором о scope.
|
||||
**`## Инварианты`** — то, что твоя реализация обязана соблюсти (дословность
|
||||
хранения, «сохранили — значит приняли» и подобное). **`## Прод и поток`** — объёмы
|
||||
и представление данных: решение, разумное на сотне записей, неразумно на
|
||||
миллионе. **`## Карта`** — где конвенции и где файл наблюдений на живых данных.
|
||||
- **`docs/passport.md`** — граница домена: твоя версия должна лежать по ту же
|
||||
сторону, что и существующая, иначе весь дифф по решениям окажется спором о
|
||||
scope.
|
||||
- **`CLAUDE.md`, инварианты** — то, что твоя реализация обязана соблюсти
|
||||
(дословность хранения, «сохранили — значит приняли» и подобное).
|
||||
- **`docs/research/` и `docs/database.md` вместе** — измеренные объёмы и
|
||||
представление данных. Решение, разумное на сотне записей, неразумно на
|
||||
миллионе; и то и другое читается вместе, порознь они ничего не решают.
|
||||
- **`docs/conventions/`** — твоя версия должна быть сравнимой по форме.
|
||||
|
||||
**Брифа нет** — пиши свою версию по спеке и конвенциям, но: `critical` по
|
||||
основанию «нарушен инвариант проекта» не присваивай (инвариантов ты не знаешь, а
|
||||
именно они чаще всего объясняют чужое решение), объёмы не предполагай и в границы
|
||||
покрытия дай строку «брифа проекта нет: инварианты и профиль нагрузки прогону
|
||||
неизвестны, расхождения по этим основаниям не оценивались». Без брифа риск
|
||||
конкретно этого прохода максимален: твоя версия проще, потому что не знает, чего
|
||||
проект боится.
|
||||
Карта «что нужно проходу → где лежит» —
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||
|
||||
**Деградация поразрядная.** Нет инвариантов в `CLAUDE.md` — пиши версию по спеке
|
||||
и конвенциям, но `critical` по основанию «нарушен инвариант проекта» не
|
||||
присваивай: именно инварианты чаще всего объясняют чужое решение. Нет объёмов в
|
||||
`docs/research/` — не предполагай их. Строка в границы покрытия называет, чего
|
||||
именно не было. **Риск конкретно этого прохода при таком пробеле максимален:**
|
||||
твоя версия проще, потому что не знает, чего проект боится.
|
||||
|
||||
**Тебя запускают по триггеру, а не всегда.** Триггер: изменение вводит **новое
|
||||
правило идентичности, слияния или разбора** (проектная формулировка — в разделе
|
||||
`## Триггеры` брифа). Вне его твой счёт — самый большой в конвейере (он
|
||||
`docs/review.md`, если он там записан). Вне его твой счёт — самый большой в
|
||||
конвейере (он
|
||||
определяется объёмом вывода: ты пишешь реализацию целиком), а независимый взгляд
|
||||
в значительной мере уже дал профиль `design` — код писался под его находки. Если
|
||||
тебя позвали, значит случай тот самый: работай в полную глубину и не экономь на
|
||||
@@ -44,8 +50,8 @@ color: purple
|
||||
|
||||
Тебе дают: требования из дельта-спеки, сигнатуры соседей, с которыми узел
|
||||
договаривается, назначение узла. Описание внешнего мира (формат входа, поведение
|
||||
источника) читай в документации проекта и в файле наблюдений на живых данных из
|
||||
раздела `## Карта` брифа — это описание мира, а не реализации под ревью.
|
||||
источника) читай в `docs/architecture.md` и в `docs/research/` — это описание
|
||||
мира, а не реализации под ревью.
|
||||
Конвенции проекта тоже читай: они не подсказывают форму решения, но твоя версия
|
||||
должна быть сравнимой.
|
||||
|
||||
|
||||
@@ -15,20 +15,24 @@ color: purple
|
||||
(точный путь конвейер передаёт в задании). Русская проза, идентификаторы — в
|
||||
оригинале.
|
||||
|
||||
## Что берёшь из брифа
|
||||
## Что берёшь из документов проекта
|
||||
|
||||
- **`## Типовые узлы`** — роды узлов этого проекта и специфичные для них свойства.
|
||||
Это материал для требования «минимум три пункта специфичны для типа узла».
|
||||
- **`## Инварианты`** и **`## Проект`** — чтобы рубрика не противоречила тому, что
|
||||
проект защищает и чем он себя ограничил.
|
||||
- **`## Прецеденты`** — классы дефектов, уже случавшихся здесь: свойство,
|
||||
- **`docs/review.md`, «Типовые узлы»** — рода узлов этого проекта и специфичные
|
||||
для них свойства. Это материал для требования «минимум три пункта специфичны
|
||||
для типа узла».
|
||||
- **`CLAUDE.md`, инварианты** и **`docs/passport.md`** — чтобы рубрика не
|
||||
противоречила тому, что проект защищает и чем он себя ограничил.
|
||||
- **`docs/review.md`, журнал** — классы дефектов, уже случавшихся здесь: свойство,
|
||||
сформулированное по прецеденту, сильнее любого общего.
|
||||
|
||||
**Брифа или этих разделов нет** — порождай рубрику по общей практике, но
|
||||
`critical` по основанию «нарушен инвариант проекта» (в фазе 2) не присваивай и
|
||||
дай в границы покрытия строку: «брифа проекта нет: рода узлов, инварианты и
|
||||
прецеденты неизвестны; требование «минимум три пункта специфичны для типа узла»
|
||||
выполнено по общей практике, а не по этому проекту».
|
||||
Карта «что нужно проходу → где лежит» —
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||
|
||||
**Этих документов нет** — порождай рубрику по общей практике, но `critical` по
|
||||
основанию «нарушен инвариант проекта» (в фазе 2) не присваивай и дай строку:
|
||||
«`docs/review.md` и инвариантов нет: рода узлов и прецеденты неизвестны;
|
||||
требование «минимум три пункта специфичны для типа узла» выполнено по общей
|
||||
практике, а не по этому проекту».
|
||||
|
||||
## Порядок фаз обязателен
|
||||
|
||||
@@ -46,7 +50,7 @@ color: purple
|
||||
|
||||
- отсортирована по важности, а не по порядку прихода в голову;
|
||||
- **минимум три пункта специфичны для типа узла**, а не общие слова. Ориентиры
|
||||
по родам узлов (проектные — в брифе):
|
||||
по родам узлов (проектные — в `docs/review.md`):
|
||||
- *парсер входного формата* — поведение на усечённом и враждебном входе,
|
||||
границы размера, отсутствие паники, детерминизм, судьба незнакомых полей;
|
||||
- *HTTP-обработчик приёма* — валидация формы конверта до записи, лимит тела и
|
||||
@@ -70,15 +74,15 @@ color: purple
|
||||
в середине слияния запись остаётся либо прежней, либо полной», а не «аккуратно
|
||||
работать с контекстом»;
|
||||
- пункты, специфичные для проекта, приветствуются, но не должны вытеснить общие:
|
||||
если вся рубрика — пересказ инвариантов из брифа, проход выродился в
|
||||
если вся рубрика — пересказ инвариантов из `CLAUDE.md`, проход выродился в
|
||||
applicative;
|
||||
- **отдельным пунктом — узел, читающий состояние, которое сам же меняет.**
|
||||
Спроси, остаётся ли результат функцией от того, что **уже произошло**, а не от
|
||||
того, в каком порядке исполнялись параллельные операции и когда именно узел
|
||||
посмотрел на состояние. Класс: запрос берёт «последнее выведенное значение»
|
||||
вообще вместо последнего предшествующего — и пересборка перестаёт
|
||||
воспроизводить состояние. Случаи этого проекта — в разделе `## Прецеденты`
|
||||
брифа. Тот же вопрос на **готовом коде** задаёт эксплуатационный проход
|
||||
воспроизводить состояние. Случаи этого проекта — в журнале `docs/review.md`.
|
||||
Тот же вопрос на **готовом коде** задаёт эксплуатационный проход
|
||||
(вопрос 9); здесь он задаётся дизайну.
|
||||
|
||||
Выведи рубрику **до** любых находок. Она — часть результата, даже если код
|
||||
|
||||
@@ -15,22 +15,26 @@ Development на OpenSpec). Оптика — требования, а не ст
|
||||
ключевые слова спек (`SHALL`, `GIVEN/WHEN/THEN`) — в оригинале. Читай реальные
|
||||
файлы перед выводом, ничего не выдумывай.
|
||||
|
||||
## Что берёшь из брифа проекта
|
||||
## Что берёшь из документов проекта
|
||||
|
||||
- **`## Инварианты`** — по ним проверяется, отражены ли в спеке задетые свойства,
|
||||
и по ним же присваивается severity. Цитируй пункт дословно, когда ссылаешься.
|
||||
- **`## Карта`** — где актуальные спеки, где дельты, где архитектура и **где файл
|
||||
наблюдений на живых данных**. Там же — **нарезка capability и миграционное
|
||||
состояние спек**: по какому признаку проект режет capability и какие темы ещё
|
||||
не переехали из документации в спеки. Без этого пункта непереехавшая тема
|
||||
читается как пробел в спеке, и находка уходит в пустоту.
|
||||
- **`## Проект`** — граница домена: требование, переносящее понятие через неё, —
|
||||
находка в спеку, а не в код.
|
||||
- **`CLAUDE.md`, инварианты** — по ним проверяется, отражены ли в спеке задетые
|
||||
свойства, и по ним же присваивается severity. Цитируй пункт дословно, когда
|
||||
ссылаешься.
|
||||
- **`docs/architecture.md`** — компоненты и capability, и **что из них уже
|
||||
переехало в нормативные спеки**. Без этого непереехавшая тема читается как
|
||||
пробел в спеке, и находка уходит в пустоту.
|
||||
- **`docs/research/`** — как внешний мир ведёт себя на самом деле.
|
||||
- **`docs/passport.md`** — граница домена: требование, переносящее понятие через
|
||||
неё, — находка в спеку, а не в код.
|
||||
|
||||
**Брифа нет** — сверяй только спеку с кодом, `critical` по основанию «нарушен
|
||||
инвариант проекта» не присваивай и дай в границы покрытия строку: «брифа проекта
|
||||
нет: инварианты, граница домена и состояние переноса capability в спеки
|
||||
неизвестны; отражение инвариантов в спеке не проверялось».
|
||||
Пути спек жёсткие: актуальные — `openspec/specs/<capability>/spec.md`, дельты —
|
||||
`openspec/changes/<id>/specs/`. Карта «что нужно проходу → где лежит» —
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||
|
||||
**Нет инвариантов в `CLAUDE.md`** — сверяй только спеку с кодом, `critical` по
|
||||
основанию «нарушен инвариант проекта» не присваивай и дай строку: «инвариантов в
|
||||
`CLAUDE.md` нет: отражение инвариантов в спеке не проверялось». Нет
|
||||
`docs/passport.md` — граница домена неизвестна, и это отдельная строка.
|
||||
|
||||
## Источник требований
|
||||
|
||||
@@ -40,19 +44,19 @@ Development на OpenSpec). Оптика — требования, а не ст
|
||||
находка.
|
||||
|
||||
Дополнительно поднимаешь: `design.md` и `tasks.md` change, затронутые актуальные
|
||||
спеки, инварианты из брифа. Если тема ещё не перенесена в спеки и живёт только в
|
||||
документации проекта — источник истины там, и это фиксируется в границах
|
||||
покрытия. Отдельно: файл наблюдений на живых данных (если он есть в карте) нормой
|
||||
не является, но именно там записано, как внешний мир ведёт себя на самом деле;
|
||||
требование, противоречащее наблюдению, — повод для находки в спеку.
|
||||
спеки, инварианты из `CLAUDE.md`. Если тема ещё не перенесена в спеки и живёт
|
||||
только в `docs/architecture.md` — источник истины там, и это фиксируется в
|
||||
границах покрытия. Отдельно: `docs/research/` нормой не является, но именно там
|
||||
записано, как внешний мир ведёт себя на самом деле; требование, противоречащее
|
||||
наблюдению, — повод для находки в спеку.
|
||||
|
||||
## Режим 1 — дизайн/спеки ДО кода
|
||||
|
||||
Проверяешь change как артефакт: полнота покрытия постановки; сценарии
|
||||
`GIVEN/WHEN/THEN` без дыр, противоречий и недостижимых веток; scope не раздут и
|
||||
не урезан молча; согласованность с текущими спеками и нарезкой capability; в
|
||||
спеке отражены **задетые инварианты из брифа** — поимённо, а не «безопасность
|
||||
учтена».
|
||||
спеке отражены **задетые инварианты из `CLAUDE.md`** — поимённо, а не
|
||||
«безопасность учтена».
|
||||
|
||||
Прогоняй `openspec validate --strict <id>` сам — это оракул, а не догадка.
|
||||
|
||||
@@ -111,7 +115,7 @@ Development на OpenSpec). Оптика — требования, а не ст
|
||||
### 2.4 Право сомневаться в требовании
|
||||
|
||||
Для верификатора спека обычно аксиома — здесь это ограничение **снято явно**.
|
||||
Если требование выглядит неверным (противоречит инварианту из брифа, делает
|
||||
Если требование выглядит неверным (противоречит инварианту из `CLAUDE.md`, делает
|
||||
невозможным штатный сценарий, теряет данные, которых потом не восстановить) —
|
||||
скажи об этом прямо, с последствием. Такая находка всегда `Действие: развилка`:
|
||||
менять спеку — решение человека.
|
||||
|
||||
@@ -22,24 +22,31 @@ color: green
|
||||
## Вход
|
||||
|
||||
Сырые выводы всех запущенных проходов, `git diff <база>..HEAD`, **список
|
||||
запущенных проходов**, профиль и режим прогона, путь к брифу проекта. Дельта-спеки
|
||||
— по мере надобности.
|
||||
запущенных проходов**, профиль и режим прогона. Дельта-спеки — по мере
|
||||
надобности.
|
||||
|
||||
Из брифа тебе нужны: **`## Инварианты`** (что делает находку `critical` и что
|
||||
делает её развилкой), **`## Прод и поток`** (что необратимо — от этого зависит
|
||||
ранжирование), **`## Прецеденты`** (готовые оракулы: находка того же класса, что
|
||||
уже воспроизводился здесь, подтверждается ссылкой на прецедент),
|
||||
**`## Типовые ложноположительные`** (единственный проектный вход в шаг 4),
|
||||
**`## Недоступно проверке`** — оба подраздела, они целиком уезжают в границы
|
||||
покрытия и **не сливаются в один список**, — **`## Команды`** (что запускать
|
||||
запрещено).
|
||||
Из документов проекта тебе нужны:
|
||||
|
||||
**Брифа нет** — работай по общим правилам, но: ни одну находку не поднимай до
|
||||
`critical` по основанию «нарушен инвариант проекта» (сослаться не на что),
|
||||
ранжируй по обратимости, выведенной из кода, и назови это предположением. Первой
|
||||
строкой сводки — «прогон шёл без брифа проекта (<причина>)», и это же идёт в
|
||||
границы покрытия. Одинаковая строка «брифа нет» без причины перестаёт читаться
|
||||
на третьей задаче — причину сохраняй.
|
||||
- **`CLAUDE.md`, инварианты** — что делает находку `critical` и что делает её
|
||||
развилкой; там же, **что необратимо** (от этого зависит ранжирование) и что
|
||||
запускать запрещено;
|
||||
- **`docs/review.md`, журнал** — готовые оракулы: находка того же класса, что уже
|
||||
воспроизводился здесь, подтверждается ссылкой на запись;
|
||||
- **`docs/review.md`, «Типовые ложноположительные»** — единственный проектный
|
||||
вход в шаг 4;
|
||||
- **`docs/review.md`, «Недоступно проверке»** — оба подраздела, они целиком
|
||||
уезжают в границы покрытия и **не сливаются в один список**.
|
||||
|
||||
Карта «что нужно проходу → где лежит» —
|
||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||
|
||||
**Деградация поразрядная, и ты — тот, кто сводит её строки в одну.** Свою часть
|
||||
тоже называй: нет инвариантов в `CLAUDE.md` — ни одну находку не поднимай до
|
||||
`critical` по этому основанию (сослаться не на что), ранжируй по обратимости,
|
||||
выведенной из кода, и назови это предположением. Нет `docs/review.md` — отсев
|
||||
ложноположительных слепой, и это отдельная строка. **Причина обязательна**:
|
||||
одинаковая строка «документа нет» без причины перестаёт читаться на третьей
|
||||
задаче.
|
||||
|
||||
## Порядок. Не меняй его
|
||||
|
||||
@@ -65,12 +72,12 @@ color: green
|
||||
рассуждение о ней ничего не доказывает;
|
||||
- выполнить команду и приложить вывод;
|
||||
- показать поимённое положение гайда, строку конвенции проекта или **дословный
|
||||
пункт из раздела `## Инварианты` брифа**;
|
||||
- сослаться на наблюдение в файле живых данных проекта — оно сильнее любого
|
||||
пункт из раздела инвариантов `CLAUDE.md`**;
|
||||
- сослаться на наблюдение в `docs/research/` — оно сильнее любого
|
||||
рассуждения о том, «как должно быть».
|
||||
|
||||
Бюджет — по одной попытке на находку. Не превращай триаж в отдельное
|
||||
расследование. Ничего не запускай на рабочих данных — запреты в брифе.
|
||||
расследование. Ничего не запускай на рабочих данных — запреты в `CLAUDE.md`.
|
||||
|
||||
### 3. Понижение неподтверждённого
|
||||
|
||||
@@ -92,7 +99,7 @@ severity:
|
||||
перестановка функций, «лучше вынести в отдельный файл», предложения обобщить
|
||||
работающий частный случай.
|
||||
|
||||
**Проектный вход сюда один — раздел `## Типовые ложноположительные` брифа.**
|
||||
**Проектный вход сюда один — «Типовые ложноположительные» в `docs/review.md`.**
|
||||
Там перечислены находки, которые в этом проекте выглядят убедительно и всегда
|
||||
неверны: они выбрасываются со ссылкой на пункт и с пометкой почему, а не
|
||||
«смягчаются». Классический обитатель раздела — предложение «нормализовать» то,
|
||||
@@ -105,8 +112,8 @@ severity:
|
||||
|
||||
Не по severity как таковой и не по числу нашедших проходов. **Порча и потеря
|
||||
данных с низкой вероятностью важнее гарантированного неудобства**, и перевес тем
|
||||
сильнее, чем менее обратимы данные в этом проекте (раздел `## Прод и поток`
|
||||
брифа). Падение сервиса, наоборот, обычно обратимо.
|
||||
сильнее, чем менее обратимы данные в этом проекте (`CLAUDE.md`, что необратимо).
|
||||
Падение сервиса, наоборот, обычно обратимо.
|
||||
|
||||
Второй по весу класс — **молчание**: отказ, о котором владелец не узнает, дороже
|
||||
отказа, который виден сразу.
|
||||
@@ -128,7 +135,7 @@ severity:
|
||||
- **инлайн** — оркестратор чинит сам, не спрашивая и не логируя. Правка локальна,
|
||||
решение однозначно, объём right-size.
|
||||
- **развилка** — цена сопоставима с переработкой, либо меняется scope, либо
|
||||
трогается инвариант из брифа, либо надо менять спеку. Формулируй готовым
|
||||
трогается инвариант из `CLAUDE.md`, либо надо менять спеку. Формулируй готовым
|
||||
вопросом с 2–3 вариантами: оркестратор перенесёт его почти дословно.
|
||||
|
||||
Сомневаешься — ставь `развилка`. Ошибка в сторону лишнего вопроса дешевле
|
||||
@@ -152,7 +159,7 @@ severity:
|
||||
- какие **не** запускались и почему (профиль, бюджет, недоступный инструмент,
|
||||
остановленный прогон);
|
||||
- что каждый запущенный проход **не мог проверить в принципе** — из его charter'а;
|
||||
- **что осталось целиком на человеке** — раздел `## Недоступно проверке` брифа,
|
||||
- **что осталось целиком на человеке** — «Недоступно проверке» из `docs/review.md`,
|
||||
**двумя отдельными списками**: «не проверит ни один проход» и «перестали
|
||||
проверять сознательно». Слитый список бесполезен: при следующем промахе первый
|
||||
вопрос — «не тот ли это класс, который мы перестали проверять», и ответить на
|
||||
@@ -160,8 +167,10 @@ severity:
|
||||
инцидентов, поведение под реальным потоком, поведение внешних систем в их
|
||||
версиях, завязка потребителей на текущее поведение и вопрос «а нужна ли эта
|
||||
функциональность вообще»;
|
||||
- если брифа не было — строку об этом **с причиной**: инварианты, модель угроз и
|
||||
профиль нагрузки прогону были неизвестны, потому что <причина>.
|
||||
- **каких документов проекта не хватило** — строкой на каждый, **с причиной**:
|
||||
«`docs/security.md` в проекте нет», «есть, но периметр не назван». Строки
|
||||
приходят из проходов; слить их в одну «документации не было» нельзя —
|
||||
деградация поразрядная, и разные пробелы чинятся разным.
|
||||
|
||||
Формулировка «критичных проблем не обнаружено» **запрещена** без этой секции: она
|
||||
потребляет ощущение проверенности, ничего не гарантируя, и это хуже, чем
|
||||
|
||||
Reference in New Issue
Block a user