В октябрьском сценарии самая дорогая ошибка review возникает не там, где reviewer не нашёл все дефекты, а там, где он сделал вывод сильнее evidence. Например, видит обработку ошибки, но не знает состояние до неё, кому виден результат и что считается обратимым. Комментарий звучит завершённо, однако риск эксплуатации или контракта остаётся без владельца. Цена — ложная определённость: будущая миграция получает не вопрос, а чужую догадку в роли решения.
Стиль сам по себе не опасен, но он удобен: его можно обсудить без модели риска. Поэтому в октябре 2026 я бы спроектировал mechanism не как рейтинг reviewer, а как цепочку риск → нужное доказательство → допустимый вывод → gate. Это план, не отчёт о проведённом review. Источники зафиксированы на 31.07.2026; named literals не обращаются к PR, CI, сети или production, а их positive branch заканчивается только bounded-review-handoff.
Риск — это граница, на которой меняется смысл
Для review полезно классифицировать не «сложность diff», а тип границы. Contract risk возникает, когда меняются форма данных, optionality, порядок полей или ожидание потребителя. Operational risk возникает, когда значение имеет переход состояния, повтор, timeout, отказ или наблюдаемость. Security risk возникает, когда решение зависит от того, кто доверен, какие входы допускаются и к чему приводит злоупотребление. Один change может затрагивать несколько границ; тогда нельзя закрыть все одной общей репликой.
Класс риска не равен severity и не предсказывает ущерб. Он лишь выбирает минимальный вопрос. Если риск неизвестен, gate должен остановить разговор раньше, чем появится «скорее всего безопасно». Такой stop не обвиняет автора. Он честно сообщает: текущий input недостаточен, чтобы выбрать набор evidence. Это дешевле, чем требовать от reviewer угадать историю системы по нескольким строкам.
| Если известно | Ещё нужно назвать | Тогда допустимо | Запрещено утверждать |
|---|---|---|---|
| форма поля меняется | consumers и возврат формы | запросить contract evidence | что все клиенты совместимы |
| есть ветка ошибки | state transition и наблюдаемое последствие | сформулировать operational question | что отказ обработан |
| есть проверка входа | trust boundary и abuse consequence | эскалировать security question | что граница защищена |
| есть только стиль | отсутствие иных рисков | оставить optional note | что изменение безопасно |
Evidence должно уменьшать конкретную неопределённость
Хорошее evidence не обязано быть большим. Для contract migration fixed-schema-delta фиксирует старую и будущую форму в учебной модели; fixed-consumer-map перечисляет named categories потребителей; fixed-rollback-note удерживает вопрос о возврате. Эти три слова не доказывают выполнение операции. Они уменьшают три разные неопределённости: изменение формы, охват получателей и обратимость. Поэтому один screenshot, один тест или один комментарий автора не подменяет их набор.
У operational risk другая геометрия. Нужна не карта consumers, а state transition: что было до ветки, что происходит после неё, возможно ли повторение. Failure mode называет, какой отказ рассматривается, но не превращает его в статистику. Observation boundary показывает, что в будущем вообще можно было бы наблюдать, но не заявляет, что измерение уже существует. Такой разбор оставляет результат скромным: вопрос может быть подготовлен, но система не объявлена устойчивой.
Gate должен быть fail-closed
Fail-closed здесь означает ровно одно: неизвестная или неполная модель не получает более сильный вывод. Неизвестный risk class возвращает stop-unknown-risk-class. Неполный набор возвращает stop-insufficient-evidence с точным списком missing. Попытка закрыть contract risk style comment возвращает stop-style-displaces-risk. Механизм не пытается восстановить намерение автора, не ищет нужные данные в мире и не предлагает обходное «можно потом проверить».
У такого stop есть социальная польза. Он делает спор проверяемым: можно добавить missing consumer map или переименовать риск, а не выигрывать дискуссию авторитетом. Одновременно он защищает от ложной эскалации. Нельзя назвать security problem лишь потому, что diff непривычен; требуются trust boundary, input rule и abuse consequence. Gate направляет к владельцу вопроса, но не изображает найденную уязвимость и не создаёт инцидент.
Исполнимый пример ветки stop
import { createFixedReviewCase, assessFixedDecisionEvidence } from './upgrade-2026-10.mjs';
const incomplete = createFixedReviewCase('missing-consumer-map-v1');
const result = assessFixedDecisionEvidence(incomplete);
console.log({ status: result.status, missing: result.missing, next: result.nextAction });
// { status: 'stop-insufficient-evidence', missing: ['fixed-consumer-map'], next: 'request-only-the-named-missing-evidence' }
Этот public export работает над замороженным JSON clone и ничего не читает извне. fixed-consumer-map отсутствует в заранее заданном input, поэтому результат не «проверяет клиентов» и не создаёт задачу. Он просто запрещает переход к более сильной фразе. Такой literal полезен для будущего стандарта: условие stop можно обсудить до появления реального change, когда ни один участник не должен защищать конкретный implementation.
Допустимый вывод должен быть проверяемо слабым
Хорошая формулировка результата содержит глагол, который соответствует входу. При наличии schema delta и consumer map можно сказать: «в плановой модели сформирован вопрос о совместимости». Нельзя сказать: «совместимость доказана». При наличии state transition можно спросить о повторе; нельзя утверждать, что retry безопасен. При наличии trust boundary можно эскалировать к владельцу security; нельзя сообщить, что уязвимость найдена. Эта разница не стилистическая. Она определяет, какие последующие действия читатель сочтёт уже разрешёнными.
Низкая сила вывода полезна ещё и тем, что переживает изменение вводных. Завтра окажется, что consumer category была неполной или failure mode шире. Если hand-off обещал только уточнение, его не нужно ретроспективно переписывать как ошибочный вердикт. Если он уже заявил safety, команда вынуждена объяснять, почему уверенность появилась раньше evidence. Поэтому механизм сознательно выбирает неброские статусы. Они дают следующему владельцу маршрут, но не забирают у него право принять реальное решение.
Граница между stop и эскалацией
Stop и escalation часто смешивают, хотя у них разные причины. Stop означает: модель не содержит условие, без которого нельзя вывести даже плановый следующий шаг. Escalation означает: условие названо, но его владелец или трактовка лежат за пределом роли reviewer. Например, отсутствие trust boundary — stop; названная trust boundary с неясным abuse consequence — вопрос владельцу security. В обоих случаях нельзя добавить температуру фразой «критично», пока severity не является отдельным доказанным измерением.
Такое разделение уменьшает обратную связь с шумом. Автор future change не получает длинный список людей, которых нужно позвать «на всякий случай». Он сначала видит missing input. Если input полон, карточка формулирует, кому и зачем передаётся вопрос. В октябрьском сценарии это только учебная маршрутизация; она не открывает доступ к реальным владельцам и не создаёт процессное обязательство. Но она позволяет проверить, что путь эскалации не подменяет пробел evidence.
Контрпример: знакомое слово не является моделью
Слова rollback, retry и validation часто вызывают ощущение, что система уже описана. В matrix это лишь ярлыки. Rollback note без старой формы не объясняет обратимость. Retry без state transition не говорит, повторяется ли побочный эффект. Validation без input rule не указывает, что именно отвергается. Reviewer не должен атаковать знакомое слово; достаточно попросить связать его с минимальным входом. Если связи нет, термин остаётся намерением, не evidence.
Escalation — передача вопроса, не передача вины
Эскалация нужна, когда reviewer понимает тип риска, но не владеет контекстом решения. Для контракта вопрос может уйти владельцу schema; для операции — владельцу state machine или поддержки; для security — тому, кто определяет trust boundary. Handoff должен содержать риск, недостающее evidence, точный вопрос и ограничение вывода. В нём не должно быть «срочно», если нет названной причины, и не должно быть решения за получателя.
NIST SSDF описывает высокоуровневые практики secure software development, которые интегрируются в разные SDLC. Это полезная внешняя рамка для того, чтобы не вырывать security из жизненного цикла. Но она не диктует состав нашей матрицы и не заменяет локальные роли. Поэтому в сценарии источник поддерживает vocabulary риска, а decision gate остаётся явно проектным и ограниченным named literals.
Последовательность планирования gate
- Записать один будущий scenario и отделить изменение формы от предположения о его последствиях.
- Назвать ровно один risk class или вернуть stop unknown-risk-class.
- Сопоставить классу минимальный набор evidence, не добавляя нерелевантные проверки.
- Проверить, что каждое evidence снимает отдельную неопределённость.
- Сформулировать допустимый вывод слабее, чем факт работоспособности, approval или release.
- Передать только synthetic hand-off либо вернуть missing evidence без выдуманного диагноза.
Границы mechanism и следующий шаг
Эта модель не измеряет severity, не назначает SLA и не делает triage реального потока комментариев. Она не может доказать совместимость, отсутствие уязвимости или корректность migration. Её сила намеренно меньше: создать одинаковый язык для остановки вывода в момент, когда input ещё слаб. Если команде нужен количественный риск, это отдельная модель с данными, владельцем и правом на их использование.
Следующий шаг в плане на октябрь — прогнать четыре named fixed cases: полный contract input, отсутствующий consumer map, style вместо риска и неизвестный класс. Обсуждать нужно не то, «хорош ли reviewer», а то, дают ли статусы ожидаемые границы. После этого можно решить, нужны ли отдельные строки для API versioning, data retention или rollout; их нельзя молча добавить в existing gate.
Проверяемые источники
- NIST SP 800-218: Secure Software Development Framework (SSDF) Version 1.1 — версия: February 2022, NIST SP 800-218, DOI 10.6028/NIST.SP.800-218. NIST SSDF задаёт высокоуровневую рамку интегрируемых практик secure software development и общий словарь рисков. Граница: Источник не подтверждает риск, уязвимость, review или процесс конкретной команды.
- RFC 2119: Key words for use in RFCs to Indicate Requirement Levels — версия: BCP 14, March 1997, DOI 10.17487/RFC2119. RFC используется для осторожного объяснения силы обязательных формулировок в спецификациях. Граница: Он не назначает severity, владельца или escalation path данного плана.
- RFC 8174: Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words — версия: BCP 14, May 2017, DOI 10.17487/RFC8174. RFC уточняет условие интерпретации ключевых слов BCP 14. Граница: Документ не превращает статус fixed validator в approval или требование к реальному change.