Удержите задачу в объявленных границах правки
Помогает удержать фокус на конкретной задаче и не расползтись по кодовой базе. Определяет границы изменений и предупреждает о scope creep. Используйте когда задача начинает расти или хочется 'заодно поправить'.
Как агент работает
Граница, которую нельзя проверить, это не граница, а настроение: «не расползаться» и «сделать аккуратно» два человека прочитают по-разному и оба будут правы. Критерий готовности обязан содержать три вещи: что запускаем, на каких данных и что считаем успехом. «Синхронизация работает» критерием не является, а «команда с флагом dry-run на выгрузке от конкретной даты даёт ноль ошибок» является. Если критерий не укладывается в одно проверяемое предложение, задача не одна, и резать её надо до того, как написана первая строка кода.
Список файлов составляется до начала работы и сверяется по ходу через git diff --stat. Расширять границу можно, но не молча: новый файл сопровождается фразой «добавляю его, потому что без него критерий не выполнится», и если такого «потому что» нет, файл не нужен. Расползание считается не дисциплиной, а деньгами: правка «на пятнадцать минут» в соседнем модуле с учётом выросшего ревью и вероятного разбора выходит примерно в полтора часа вместо четверти. Исключение, произнесённое заказчику вслух, работает; записанное только в голове не работает.
Время ревью растёт с размером диффа, а число найденных дефектов не растёт. До 200 строк дифф читается построчно, 200-400 по диагонали и режется на два PR, на 400-1000 ревьюер ищет, за что зацепиться, и правит стиль вместо логики, больше 1000 даёт «LGTM» через шесть минут, то есть код ушёл в прод непрочитанным. Смешанный коммит нельзя откатить наполовину: git revert снимает его целиком, и если рядом с фиксом выгрузки лежит переименование в биллинге, дежурный ночью выбирает между откатом обоих и разбором конфликта под давлением.
Каждая находка по ходу работы попадает в одну из трёх корзин по двум вопросам: блокирует ли она критерий готовности буквально и есть ли у неё жертва прямо сейчас (чужие данные в чужом кабинете, платёж не туда, персональные данные в логах, ключ в открытом виде). Да на любой: чинить немедленно, причём дефект безопасности отдельным коммитом с собственным сообщением. Нет на оба: записать задачей в момент находки, с воспроизведением и путём к файлу, либо игнорировать явно, назвав причину вслух.
Единственное исключение составляет связанный рефакторинг, и работает оно по правилу двух коммитов: рефакторинг идёт отдельно и строго до изменения поведения, а его чистота проверяется тем, что тесты прошли без правок самих тестов. Исключение не применяется, когда рефакторинг больше самой правки: ради двухстрочного фикса не перекраивают 300 строк, потому что некрасивый фикс откатывается за секунду, а красивый нет. Если границу задал заказчик и она прошла поперёк связности кода, навык не спорит абстрактно, а показывает получающийся список файлов и предлагает другой разрез.
1. Граница, которую можно проверить
«Не расползаться» и «сделать аккуратно» не проверяются: два человека прочитают их по-разному и оба будут правы.
1.1 Четыре поля Scope Lock: заполни до начала работы
Не заполняется хоть одно поле: начинай не с кода, а с уточняющего вопроса.
Пример типовой задачи российского SMB:
1.2 Критерий готовности
Обязан содержать три вещи: что запускаем, на каких данных, что считаем успехом.
| Не критерий | Критерий |
|---|---|
| «Синхронизация работает» | «python -m sync.stocks --dry-run на выгрузке от 2026-07-27 даёт 0 ошибок» |
| «Форма стала быстрее» | «TTFB карточки заказа ≤ 400 мс на 20 запросах подряд, замер curl -w» |
| «Убрал баг с ценами» | «1 249,50 ₽ уходит в Ozon как 1249.5, тест test_price_precision зелёный» |
| «Отрефакторил модуль» | результат не наблюдаем, это не задача (раздел 4) |
Критерий не укладывается в одно проверяемое предложение, задача не одна: режь (раздел 5) до кода.
2. Расползание: вопрос стоимости, а не дисциплины
2.1 Ревью: время растёт, находимость падает
После первых 200–400 изменённых строк растёт не количество найденного, а количество пропущенного. Это рабочая эвристика: калибруй под свою команду, ссылками на чужие исследования не подкрепляй, проверь на своей истории ревью.
| Дифф | Что происходит | Что делать |
|---|---|---|
| ≤ 200 строк | читается построчно, комментарии предметные | норма, цель |
| 200–400 | читается по диагонали, ловятся явные ошибки | резать на два PR |
| 400–1000 | ревьюер ищет, за что зацепиться: правки стиля вместо логики | резать обязательно |
| > 1000 | «LGTM» через шесть минут | считай, что код ушёл в прод непрочитанным |
Произноси вслух: дифф на 900 строк это не «много сделал», это «отключил ревью». Пять правок по 180 строк получают пять настоящих ревью; одна на 900: ноль.
2.2 Смешанный коммит нельзя откатить наполовину
git revert <sha> откатывает коммит целиком. Если в одном коммите фикс выгрузки остатков и «заодно» переименование в биллинге, ночью у дежурного два варианта: откатить вместе с биллингом или разбирать конфликт руками в три часа ночи. Цена в минутах простоя: час неверных остатков для продавца на маркетплейсе означает отменённые заказы, штрафы площадки, просадку карточки в выдаче.
Правило: атомарность коммита определяется откатываемостью, не размером. Вопрос перед git commit: «если это придётся откатить в одиночку, откатится ли оно в одиночку?». Нет: режь (git add -p).
2.3 Счёт в рублях
С заказчиком говори деньгами. Подставь свою ставку, для примера 3 500 ₽/час:
Правка «на 15 минут» в соседнем модуле: 0,25 ч + 0,5 ч ревью + 0,2 × 3 ч разбора ≈ 1,35 ч ≈ 4 700 ₽ вместо ожидаемых 875 ₽. Эта строка убеждает лучше слов про чистоту кода.
3. Находки по ходу работы: три корзины
Находка не проблема. Проблема: необъявленное решение, что с ней делать.
3.1 Критерий различения: два вопроса по порядку
- Блокирует ли находка критерий готовности? Буквально: без правки критерий не выполнится. Да → чинить немедленно.
- Есть ли жертва прямо сейчас? Чужие данные в чужом кабинете, платёж не туда, персональные данные в логах, ключ в открытом виде. Да → чинить немедленно; правка большая, эскалировать немедленно.
Нет на оба → «записать», если воспроизводима и адресуема. Не воспроизводится, вкусовщина или модуль скоро удаляют → «игнорировать явно».
3.2 Чинить немедленно
Только два основания: без правки недостижим критерий, либо дефект безопасности. Дефект безопасности чинится даже вне границы, но отдельным коммитом с собственным сообщением: выкатывается и откатывается независимо, в истории читается как правка безопасности.
3.3 Записать
Всё, что плохо, но подождёт: дублирование, мёртвый код, отсутствующие тесты на старое, устаревшая зависимость, второй баг без пострадавших сейчас. Записывай в момент находки туда, где команда ведёт работу (трекер, реестр долга), с воспроизведением и путём к файлу; сначала проверь, не записано ли уже.
3.4 Игнорировать явно
Игнорировать тоже решение, и его надо произнести, иначе находка вернётся третий раз и утянет. Сюда: стилевые предпочтения, «я бы назвал иначе», код с назначенной датой удаления, оптимизации без замера. Формулировка: «видел X, не трогаю: вкусовщина / модуль удаляется в августе / без профилировщика это гадание».
3.5 Шаблон записи находки
ПОСЛЕДСТВИЕ обязательное: находка без него почти всегда вкусовщина, и выясняется это при заполнении.
4. Связанный рефакторинг: единственное исключение
4.1 Правило двух коммитов
Рефакторинг идёт отдельным коммитом и строго до изменения поведения.
Коммит 1 проверяется тестами, зелёными до него и обязанными остаться зелёными: без единой правки самих тестов; пришлось поправить тест: это изменение поведения, место в коммите 2. Обратный порядок не работает: ревьюер не отличит намеренное изменение поведения от случайного.
4.2 Проверка чистоты рефакторинга
- Тесты модуля прошли без правок самих тестов.
- В диффе нет новых условий, новых значений по умолчанию, изменённых сообщений об ошибках.
- Коммит описывается предложением без слова «и».
4.3 Когда исключение не применяется
Рефакторинг больше самой правки: ради двухстрочного фикса перекроить 300 строк: две задачи. Фикс делается в текущей форме кода (некрасиво, зато локально), рефакторинг записывается. Некрасивый двухстрочный фикс откатывается за секунду, красивый на 300 строк нет.
5. Задача оказалась больше, чем казалась
Само по себе не ошибка. Ошибка: обнаружить и продолжать, надеясь, что вот-вот закончится.
5.1 Признаки в первый час
- Список файлов вырос вдвое.
- Трогаешь второй слой: был обработчик, стала схема БД; была выгрузка, стал клиент интеграции.
- Появилась фраза «сначала надо разобраться, как тут вообще устроено».
- Критерий готовности захотелось переформулировать под достижимость, самый надёжный признак: границы больше нет.
5.3 Шов, по которому режут
Хороший шов даёт часть, которую можно выкатить и которая полезна сама по себе:
- По слою: сначала правильная запись данных, потом отображение.
- По подмножеству данных: сначала товары со штрихкодом (3 385 из 3 412), отдельной задачей: 27 без него.
- По направлению обмена: сначала выгрузка в 1С, потом загрузка из неё.
- Диагностика перед лечением: сначала лог и отчёт с масштабом, потом фикс; часто после первой части выясняется, что вторая нужна не в том виде.
Плохой шов это «сделаю половину каждого»: обе половины не выкатываются, ревью невозможно, откат бессмыслен.
6. «Пока я тут» в чужом коде
- Правь ровно то, что требует критерий. Даже очевидная ошибка рядом: в «записать», с упоминанием владельца.
- Массовые правки (переименование, форматирование, автофиксы линтера) идут отдельным коммитом, лучше отдельным PR: 400 строк форматирования закрывают собой три строки логики.
- Находка критична, а замысел неясен, дешевле спросить: «в X на строке Y при пустом штрихкоде улетает исключение, это намеренно?»
- Vendored и сгенерированный код не правится вообще: правка исчезнет при следующей генерации и будет выглядеть случайной регрессией.
7. Признаки неверно заданных границ
Тянет за границу постоянно: проблема обычно в самой границе.
| Признак | Что означает | Что делать |
|---|---|---|
| Критерий не проверяется командой или наблюдением | это пожелание | переформулировать до начала работы |
| В задаче союз «и» между разными результатами | это две задачи | разрезать |
| ИСКЛЮЧЕНО пусто | границу не думали, а записали | заполнить тем, что соблазнительно |
| Каждая правка тянет правку в соседнем модуле | граница прошла поперёк связности | пересобрать по слою или модулю |
| Задача звучит как «разобраться с X» | это исследование | первая задача: отчёт, вторая: фикс |
| Оценка «пара часов» держится третий день | оценку делали до знания | пересобрать оценку вслух, не молча |
Границу задал заказчик и она прошла поперёк кода, не спорь абстрактно: покажи получающийся список файлов и предложи другой разрез с тем же бизнес-результатом.
8. Возврат к границам после отвлечения
Дорого не отвлечение, а возврат наугад: после него человек продолжает не задачу, а последнее, что попалось на глаза.
9. Формулировки: границу держит произнесённый договор
9.1 Заказчику, когда просят «заодно»
- «Это отдельная правка. Сегодняшняя задача выходит вечером, эту заведу следующей и оценю к утру, или, если она важнее, поменяем местами».
- «Сделать сейчас можно, но правки поедут одним куском: откатывать придётся всё вместе. Разными, выкатываются независимо».
- «По деньгам: сама правка 15 минут, но с ревью выросшего диффа и риском разбора при откате: около полутора часов. Отдельной задачей, те же 15 минут плюс своё маленькое ревью».
9.2 Коллеге и в ревью
- «Да, там дублирование. Записал задачей, ссылка. В этом PR не трогаю, чтобы дифф остался читаемым».
- «Переименование вынес отдельным коммитом перед фиксом: поведение не менялось, тесты те же и без правок».
- «Задача оказалась больше: выкатываю часть про товары со штрихкодом, оставшиеся 27 позиций: отдельной задачей, там другая логика сопоставления».
9.3 Себе, в момент соблазна
Один вопрос: выполнится ли мой критерий готовности без этой правки? Да → «записать», руки убрал. Нет → это часть задачи: расширь границу вслух, добавив файл в список.
Похожие навыки
Попробуйте этот навык
Зарегистрируйтесь и используйте навык «Фокус на задаче» бесплатно.