1. «У меня всё готово» уже недостаточно
Когда вы один работаете в маленькой экспериментальной ветке, легко жить по модели: «я всё проверил — значит, готово». В команде на продукте вроде Commerce OS она ломается. Merge — это не только технический факт, но и организационное решение: кто берёт последствия, если изменение задевает деньги, авторизацию, данные клиентов или продакшен-конфиг.
Сравните два PR. Первый: обновили README и команду локального запуска — здесь хватит diff review и короткого «мержим». Второй: меняется логика подтверждения возврата денег, задевается путь авторизации менеджера поддержки, нужна миграция таблицы refund_requests. Тесты могут пройти в обоих случаях. Но ответственность — разная.
Именно поэтому личная готовность задачи, CI gate и team decision gate — это не одно и то же. Они отвечают на разные вопросы.
| Уровень | Главный вопрос | Кто отвечает |
|---|---|---|
| Личная готовность задачи | «Я как автор задачи сделал всё, что должен?» | Автор PR |
| CI / quality gate | «Автоматика видит проблему?» | CI, branch rules, deterministic checks |
| Team decision gate | «Мы как команда готовы принять последствия merge/release?» | Владельцы риск-зоны, approver’ы, team lead |
Хорошая инженерная практика начинается там, где вы перестаёте путать эти три уровня. Автор может быть уверен в коде, CI может быть зелёным, но только team decision gate отвечает на вопрос: готова ли команда поставить подпись под этим изменением. Это не бюрократия — это признание того, что последствия merge касаются не только автора ветки.
2. Layer 3 — это review, а не permissions
На предыдущих модулях у вас уже появилась трёхслойная модель review. Здесь важно не смешать её с другими моделями курса. В этой модели третий слой называется Layer 3 и означает team approval gate: принять или не принять изменение после того, как локальный review и CI уже отработали.
Удобно представить это как короткую схему:
Layer 1: local review -> Layer 2: CI / quality gates -> Layer 3: team decision gate
diff, tests, lint, build, tests, approvals, rollback,
reviewer notes deterministic checks known risks, GO / HOLD
Здесь легко запутаться, потому что в прошлом модуле вам уже встречался L3 — но в модели permissions, то есть другой namespace курса. Чтобы не было каши в голове, держите простое правило: Layer 3 — про review, «кто принимает решение»; L3 permissions — «что Claude и агенты вообще имеют право делать».
| Не путать | Отвечает на вопрос | Пример |
|---|---|---|
| Layer 3 review | «Можно ли сейчас merge/release?» | GO, HOLD, required approvals |
| L3 permissions | «Что разрешено или запрещено инструментам?» | для миграций, для force push |
Это важное различие. Gate не заменяет проверки, не гоняет тесты заново и не пишет код. Он берёт уже собранное evidence — diff, CI, reviewer notes, risk notes — и превращает всё это в командное решение: «доказательств достаточно, рискуем merge/release» — или «нет, HOLD».
И да, HOLD — это нормальный результат gate. Не провал. Не стыд. Не повод срочно придумывать, как всё же продавить PR. Иногда самый зрелый ответ — это «код хороший, проверки зелёные, но мержить рано: staging не отжил нужное время, не назначен владелец риск-зоны».
3. Две опоры: risk classification и permissions
Если попытаться внедрить gate в вакууме, получится одна из двух нелепых конструкций. Либо трёхстраничный high-risk шаблон на каждую опечатку в документации — команда возненавидит саму идею. Либо строчка «ну вроде ок», которую все пролистывают. Спасают две уже знакомые опоры: risk classification и L3 team permissions.
Risk classification отвечает, насколько рискованно изменение, и определяет, какой шаблон решения нужен. Если задача low-risk, команде не нужен длинный документ с rollback plan. Если задача review-required, уже нужны не только summary, но и evidence, checks, approvals. Если задача high-risk, без rollback и явных approver’ов идти дальше нельзя.
Permissions отвечают за enforcement. Это тот случай, когда наклейка «не трогать» превращается в настоящий замок, а не остаётся бумажкой на двери холодильника. Если у вас в политике написано, что миграции и destructive commands требуют отдельного согласования, это правило должно поддерживаться не только словами, но и настройками.
Небольшой пример такого enforcement может выглядеть так:
{
"permissions": {
"ask": ["Edit(migrations/**)", "Bash(flyway *)"],
"deny": ["Bash(git push --force*)"]
}
}
Смысл здесь не в синтаксисе, а в логике. Claude или агент не могут «случайно» проскочить мимо командных правил. Если gate говорит, что high-risk изменение требует отдельного решения, permissions должны как минимум не позволять обойти это решение технически.
Получается очень здравая связка. Risk classification говорит, насколько ситуация опасна. Permissions ограничивают поле действий. Gate принимает финальное командное решение. Если убрать хотя бы один элемент, конструкция рассыплется. Без risk classification вы не понимаете, какой шаблон применять. Без permissions gate легко обойти. Без gate команда остаётся с зелёным CI, но без явного ответа на вопрос «кто принимает последствия».
4. Один gate, три масштаба риска
Самая частая ошибка новичка на этом этапе — попытаться придумать один «универсальный» шаблон на все случаи жизни. На практике это почти всегда плохая идея. Если шаблон слишком короткий, он ничего не даёт для сложных изменений. Если слишком длинный, он убивает скорость на мелочах. Поэтому production decision gate масштабируется по уровню риска.
Эту идею удобно держать в такой таблице:
| Уровень риска | Что обычно достаточно |
|---|---|
| low-risk | summary + final decision |
| review-required | risk level + evidence + checks + approvals + decision |
| high-risk | всё выше + rollback path + known limitations + явные approver’ы |
Для low-risk изменения gate может быть совсем коротким — например, обычной секцией внутри PR_DESCRIPTION.md, а не отдельным файлом. Это важный момент: не нужно создавать новый артефакт на каждый PR только ради красоты структуры. Чаще всего gate живёт прямо в описании PR или в release checklist.
Простейший low-risk блок может выглядеть так:
## Гейт production-решения
### Summary изменений
Обновлена инструкция локального запуска в README.
### Финальное решение
Merge approved. Low-risk doc change.
В этом месте не надо изображать корпоративный театр. Нет смысла писать rollback plan для абзаца в документации. Если команда начинает так делать, она сама себе роет яму из формальностей.
Для review-required изменения блок уже заметно богаче. Например, вы меняете API-флаг в Commerce OS, не затрагиваете базу и не лезете в auth, но всё же меняете рабочее поведение сервиса.
## Гейт production-решения
### Уровень риска
review-required
### Доказательства
CI green, diff reviewed, API contract preserved.
### Требуемые одобрения
Backend owner
### Финальное решение
Merge approved.
Здесь уже видно, что решение не висит в воздухе. Есть уровень риска, есть evidence, есть конкретный владелец зоны, который посмотрел изменение.
А вот high-risk вариант — совсем другая история. Если PR задевает refund flow, миграции или путь авторизации, шаблон становится полным.
## Гейт production-решения
### Уровень риска
high-risk
### Требуемые одобрения
Payments owner, security owner
### Путь отката
Revert PR, disable `refund_v2`, restore previous schema snapshot.
### Финальное решение
HOLD until staging soak test completes.
Заметьте важную вещь: здесь HOLD — это не «нам всё не нравится», а «нам нужно ещё одно доказательство перед merge». В сильной команде это считается нормой, а не слабостью.
Если же вы работаете один, Layer 3 никуда не исчезает — он просто сжимается до личного решения с явной паузой. И даже в этом случае короткий блок вида «summary + decision» помогает не мержить изменения по принципу «ну вроде работает, поехали».
5. Re-classification: риск меняется по дороге
Самая коварная иллюзия на этом этапе — думать, что риск задачи определяется в начале и потом остаётся неизменным. В реальной разработке почти никогда не так. Задача может начинаться как обычный feature PR, а через час исследования внезапно оказывается, что без миграции таблицы или изменения auth path не обойтись. И в этот момент старый risk label уже устарел.
Это называется re-classification, и относиться к ней нужно спокойно. Это не признак плохого планирования. Это нормальная реакция команды на новую информацию. Плох не пересмотр риска, а отказ его пересматривать.
Допустим, в Commerce OS вы начали задачу как review-required: нужно было добавить новый флаг для обработки возвратов. По дороге выяснилось, что старое поле в базе не вмещает новый статус, а значит, нужна миграция. В этот момент задача уже не та, с которой вы стартовали утром. У неё новый уровень риска, а значит, нужен и новый gate.
Такую переоценку очень удобно фиксировать прямо в PR:
## Лог переклассификации
- Initial: review-required
- Updated: high-risk
- Reason: DB migration required for `refund_requests.status`
- Action: added rollback and payments owner approval
Здесь важны две вещи. Во-первых, re-classification фиксируют явно, а не молча. Во-вторых, вместе с ней меняется не только label, но и весь decision process: добавляются approver’ы, rollback, возможно staging soak test или дополнительный smoke.
Отдельно стоит сказать про downscaling, то есть понижение риска. Формально оно возможно. Практически это очень опасная зона, потому что именно здесь сроки начинают шептать в ухо всякие плохие идеи. Если задача казалась high-risk, а потом вдруг «ну вроде не такая уж опасная», понижать уровень можно только с явным одобрением, а не по принципу «давайте уже протолкнём PR до вечера». Иначе gate перестаёт быть защитным механизмом и превращается в инструмент самоуспокоения.
6. Commerce OS: как это выглядит в реальном PR
Теперь соберём всё вместе в проектном контексте курса. Представьте PR в Commerce OS: команда исправляет порядок подтверждения возвратов, чтобы заявки не уходили в обработку без нужного уровня согласования. Это уже чувствительная зона, потому что затрагиваются деньги, внутренняя ролевая модель и журнал аудита. Workflow Kit к этому моменту уже поставляет QUALITY_GATES.md, RISK_CLASSIFICATION.md и настройки permissions. То есть технический каркас у нас есть. Осталось принять решение.
В реальной команде блок gate чаще всего живёт прямо в PR_DESCRIPTION.md. Не отдельным священным документом на каждое движение мышкой, а короткой секцией, которую reviewer и approver читают вместе с diff и проверками.
Например, так:
## Гейт production-решения
### Уровень риска
high-risk
### Доказательства
CI green, refund regression tests passed, reviewer notes attached.
### Требуемые одобрения
Payments owner, support lead
### Путь отката
Revert PR, disable `refund_v2`, restore previous handler.
### Финальное решение
HOLD until staging smoke and manual refund scenario pass.
Посмотрите, как здесь работают все слои сразу. Layer 1 уже дал diff review и reviewer notes. Layer 2 уже дал зелёный CI и regression tests. Risk classification уже сказал, что зона high-risk. Permissions уже не дают молча проскочить с миграцией или опасной командой. И только после этого Layer 3 делает то, чего не может сделать ни один автоматический инструмент: отвечает, готова ли команда взять это изменение в общий контур.
Именно в этот момент production readiness перестаёт быть красивой фразой из корпоративной презентации и становится обычным инженерным действием. Иногда это Merge approved. Иногда — HOLD. Иногда — просьба разделить PR на две части, потому что одна часть безопасна, а вторая уже лезет в другую risk-зону. Но в любом из этих случаев решение становится явным, читаемым и коллективно понятным. А это уже совсем другой уровень зрелости, чем простое «ну у меня локально всё прошло». И держится такой gate не на общем ощущении, а на явном следе изменения: что хотели поменять, что реально поменяли, чем это проверили и кто сказал финальное «да».
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ