Ниже — полностью вымышленный учебный сценарий. В нём нет истории частного репозитория, реального инцидента, пользователей или данных команды. Он нужен для одного практического вопроса: что делать, когда bug пересекает два модуля, а имя автора последней строки не отвечает на вопрос о поведении продукта. Симптом в симуляции такой: checkout получает неизвестный статус от gateway и показывает пользователю «успешно». Цена — неверное действие на экране и спор о том, чей это дефект.
Плохой старт выглядит так: открыть git blame, найти имя и написать ему «посмотри». Хороший старт короче, но точнее: зафиксировать статус, путь, ожидаемое поведение и три разные ответственности. Кто решает семантику статуса? Кто меняет участок кода? Кто должен посмотреть pull request? Кто проверяет результат после merge? В учебной карточке все ответы записаны рядом, поэтому разбор можно повторить без личной памяти автора.
Граница сценария и исходные факты
Симулированный сервис принимает ответ unknown от внешнего gateway. На фронтенде обработчик по умолчанию сворачивает неизвестное значение в успешный переход. История конкретной строки показывает, что её последним менял разработчик из команды checkout во время переноса parser. В каталоге рядом лежит документ с договорённостью о статусах, а path gateway закреплён за другой областью. Ни один из этих фактов не называет решение сам по себе.
Вместо попытки выбрать «правильного владельца» вначале формулируем критерий. Исправление готово, если неизвестный статус становится наблюдаемым отдельным состоянием, тест не даёт ему попасть в success, reviewer по контракту подтвердил трактовку, а после merge есть назначенная проверка. Это можно сделать и без доступа к production: проверка в сценарии — отдельный пункт, а не обещание о реально просмотренных данных.
| Наблюдение | Что оно доказывает | Чего оно не доказывает | Кому задать вопрос |
|---|---|---|---|
| git blame у parser-ветки | строку последним изменил участник checkout | он владеет правилом статусов | автору change — о контексте переноса |
| Путь /web/checkout/gateway/ | изменение попадёт в узкую интеграционную область | конкретный reviewer уже согласен с semantic change | владельцу пути и owner решения |
| Документ контракта | для статусов есть место, где ожидается правило | документ актуален без проверки | владельцу решения — о норме и исключении |
| CODEOWNERS на base branch | платформа может запросить review у совпавших owners | после merge кто-то проверит результат | author change — о follow-up |
Даже в учебном случае важно не подменять факт трактовкой. git blame корректно отвечает про последнюю модификацию линии, GitHub CODEOWNERS — про маршрут reviewer для пути. Решение о неизвестном status появляется только тогда, когда его кто-то формулирует: например, «неизвестное значение не может стать success; показываем отдельный state и сохраняем диагностический идентификатор».
Шаг 1. Собрать карту, не выбирая виноватого
В карточке дефекта создаём четыре поля. Decision owner подтверждает, что unknown означает для контракта. Code path owner помогает найти обработчик, fixture и соседние переходы. Reviewers смотрят конкретные риски в change. Follow-up owner проверяет, что после merge есть наблюдаемый результат. Английские подписи здесь только потому, что они часто встречаются в интерфейсах Git-хостингов; содержание полей остаётся простым и русским.
const issue = {
id: 'SIM-2019-12-17',
symptom: 'checkout показывает успешную оплату при неизвестном статусе',
decisionOwner: 'payments',
codePathOwner: 'checkout',
reviewers: ['payments', 'checkout'],
followUpOwner: 'checkout',
done: ['unknown status is visible', 'contract test exists', 'review is resolved'],
};
function canClose(record) {
return record.done.length === 3 && Boolean(record.followUpOwner);
}
canClose(issue); // true only for this simulated record
Фикстура не запускает внешний gateway и не изображает production. Она фиксирует форму записи: у искусственной задачи есть отдельный follow-up owner и три условия готовности. Реальный проект может хранить это в issue, pull request template или в документе рядом с контрактом. Выбирайте место, которое команда действительно читает при изменении, а не ещё один каталог ради процесса.
Шаг 2. Проверить маршрут review по пути
Для simulated change затронуты /web/checkout/gateway/status.js и /docs/checkout-contract.md. В примере CODEOWNERS узкий путь gateway должен идти после общего checkout, иначе он не получит приоритет. Документ имеет два names: один отвечает за контракт, второй — за экран. Если хостинг не поддерживает CODEOWNERS, ту же карту можно положить в описание задачи и запросить review вручную; меняется автоматизация, а не сами роли.
Перед созданием pull request автор должен посмотреть именно base branch. GitHub использует CODEOWNERS из ветки, которую change собирается изменить, и автоматически запрашивает owners для совпавших путей. Поэтому строка, добавленная только в feature branch, не доказывает, что reviewer будет назначен. В учебной проверке это не реальный PR, а вопрос к конфигурации, который нужно проверить в конкретном хостинге.
Шаг 3. Превратить review в два проверяемых вопроса
Первый review-вопрос адресован владельцу решения: допустимо ли показывать unknown как отдельное состояние, какие поля должны сохраниться для диагностики, можно ли повторить запрос. Второй — владельцу пути: не ломает ли новая ветка переход по кнопке, retry или тесты соседнего экрана. В одном pull request эти вопросы могут закрыть два человека или один. Главное — не скрыть второй вопрос за общим «looks good».
В GitHub reviewer может отправить comment, approve или request changes. Для учебного change комментарий с вопросом к contract не равен approval; approval после правки не отменяет follow-up. Если требуемое review контролируется правилами ветки, платформа может не дать merge без нужного approval. Но и тогда задача должна содержать смысл: какое правило мы проверяем и какой тест доказывает прошлый сбой.
- Создать issue с исходным симптомом, входом
unknown, неверным успехом и ожидаемым отдельным состоянием. Пометить сценарий как учебный, если это тренировочный материал. - Собрать history нужных строк и путей. Внести hashes или ссылки как факты, но не переносить имя из blame в поле decision owner без разговора о контракте.
- Назначить owner решения, пути кода, review и follow-up. Если одна роль неизвестна, stop: это незакрытый риск, а не место для случайного назначения.
- Проверить CODEOWNERS на base branch либо вручную запросить людей. Указать в PR два review-вопроса и приложить тест, где
unknownне ведёт к success. - После request changes обновить change и снова запросить review, потому что смысл diff мог заметно поменяться. После approve выполнить запланированную проверку после merge.
- Закрыть issue только с результатом follow-up: сигнал подтверждён, обнаружен новый дефект или создана связанная задача. «Merged» описывает состояние кода, но не ответ на наблюдаемый симптом.
Шаг 4. После merge не теряем технический след
В симуляции follow-up owner из checkout проверяет, что в выбранном контуре неизвестный статус не превращается в success и есть диагностический след. Если для проекта доступен только тестовый контур, так и пишем: «проверено на fixture», а не «исправлено везде». Если проверка требует другой команды, оставляем отдельную задачу с тем же идентификатором сценария. Это даёт следующему человеку путь от сигнала к решению без поиска по именам.
Сюда же относится и документ контракта. Он не должен повторять весь код; ему хватает перечислить допустимые статусы, владельца решения и ссылку на тест. Когда новый gateway-ответ появится через полгода, изменение начнётся с проверки договорённости, а не с очередного угадывания по истории строки.
Что в этом сценарии не стоит заявлять
У разборщика нет оснований говорить, что реальная команда увидела этот инцидент, что конкретный reviewer прочитал diff или что production-метрика изменилась. Сценарий специально анонимизирован и симулирован. Его ценность не в правдоподобной легенде, а в маршруте, который можно применить к настоящей задаче: отделить факты истории от ответственности, назначить review по риску и не забыть последнюю проверку после merge.
Если в реальном проекте нет CODEOWNERS или pull request workflow, не копируйте интерфейс чужой платформы. Оставьте ту же таблицу ролей в issue, добавьте путь модуля и обязуйте change иметь два ответа: кто подтвердил решение и кто подтвердил результат. Это более полезно, чем файл с владельцами, который никто не обновляет при переносе каталога.
Проверяемые источники
- Git: git-blame documentation — git blame показывает revision и автора, которые последними изменили каждую строку; это исторический факт, а не назначение текущего владельца решения
- Git: git-log documentation — git log позволяет ограничивать просмотр истории, чтобы собрать контекст изменения до исправления
- GitHub Docs: About code owners — CODEOWNERS назначает владельцев путей, запрашивает их review для изменений и использует правила из base branch pull request
- GitHub Docs: Pull request reviews — review имеет отдельные решения Comment, Approve и Request changes; правила ветки могут требовать approval перед merge