Удержите задачу в объявленных границах правки
Помогает удержать фокус на конкретной задаче и не расползтись по кодовой базе. Определяет границы изменений и предупреждает о 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) до того, как писать код.
1.3 Список файлов до начала работы
Сверяйся по ходу: sandbox_bash → git diff --stat. Файл вне ГРАНИЦЫ — это событие раздела 3, а не «ну он же связан».
Расширять границу можно, молча — нельзя. Новый файл сопровождается одной фразой вслух: «добавляю X, потому что без него критерий не выполнится». Нет такого «потому что» — файл не нужен.
1.4 Явное исключение
Исключение, произнесённое заказчику вслух, работает. Записанное только в голове — нет.
2. Расползание — вопрос стоимости, а не дисциплины
2.1 Ревью: время растёт, находимость падает
Время ревью растёт линейно с размером диффа, а число найденных дефектов — нет: после первых 200–400 изменённых строк внимание уходит, и растёт не количество найденного, а количество пропущенного. Это рабочая эвристика, а не измеренная константа: калибруй под свою команду, но порядок величины такой. Ссылками на чужие исследования не подкрепляй — проверь на своей истории ревью, там ответ точнее.
| Дифф | Что происходит | Что делать |
|---|---|---|
| ≤ 200 строк | читается построчно, комментарии предметные | норма, цель |
| 200–400 | читается по диагонали, ловятся явные ошибки | резать на два PR |
| 400–1000 | ревьюер ищет, за что зацепиться: правки стиля вместо логики | резать обязательно |
| > 1000 | «LGTM» через шесть минут | считай, что код ушёл в прод непрочитанным |
Вывод, который стоит произносить вслух: дифф на 900 строк — это не «много сделал», это «отключил ревью». Пять правок по 180 строк получают пять настоящих ревью; одна на 900 — ноль.
2.2 Смешанный коммит нельзя откатить наполовину
Аргумент не про вкус, а про механику: git revert <sha> откатывает коммит целиком. Если в одном коммите лежат фикс выгрузки остатков и «заодно» переименование в биллинге, то ночью, когда выгрузка сломает боевые остатки, у дежурного два варианта: откатить вместе с биллингом или разбирать конфликт руками в три часа ночи под давлением.
Цена считается не в удобстве, а в минутах простоя: для продавца на маркетплейсе час неверных остатков — это отменённые заказы, штрафы площадки за отмену и просадка карточки в выдаче. Ради этого не стоит экономить минуту на отдельном коммите.
Правило: атомарность коммита определяется не размером, а откатываемостью. Вопрос перед git_ops 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 Записать
Всё, что плохо, но подождёт: дублирование, мёртвый код, отсутствующие тесты на старую функциональность, устаревшая зависимость, второй найденный баг без пострадавших сейчас.
Записывай в момент находки, а не «в конце вспомню»: query_tasks — не заведено ли уже, затем manage_task с воспроизведением и путём к файлу.
3.4 Игнорировать явно
Формулировка: «видел X, не трогаю: вкусовщина / модуль удаляется в августе / без профилировщика это гадание».
3.5 Шаблон записи находки
Поле ПОСЛЕДСТВИЕ обязательное: находка без описанного последствия почти всегда оказывается вкусовщиной, и выясняется это прямо при заполнении.
4. Связанный рефакторинг — единственное исключение
4.1 Правило двух коммитов
Рефакторинг идёт отдельным коммитом и строго до изменения поведения.
Порядок именно такой, потому что коммит 1 проверяется тестами, которые были зелёными до него и обязаны остаться зелёными после — без единой правки самих тестов. Пришлось поправить тест — это уже изменение поведения, ему место в коммите 2.
Обратный порядок («сначала поведение, потом причешу») не работает: ревьюер не отличит намеренное изменение поведения от случайного, а перемешанный дифф возвращает нас к разделу 2.2.
4.2 Проверка, что рефакторинг чистый
- Тесты затронутого модуля прошли без правок самих тестов.
- В диффе нет новых условий, новых значений по умолчанию и изменённых сообщений об ошибках.
- Коммит описывается предложением без слова «и».
4.3 Когда исключение не применяется
Когда рефакторинг больше самой правки. Если ради двухстрочного фикса надо перекроить 300 строк — это две задачи: фикс делается в текущей форме кода (пусть некрасиво, зато локально), рефакторинг записывается. Некрасивый двухстрочный фикс откатывается за секунду, красивый на 300 строк — нет.
5. Задача оказалась больше, чем казалась
Само по себе не ошибка. Ошибка — обнаружить это и продолжать, надеясь, что вот-вот закончится.
5.1 Признаки в первый час
Последний признак самый надёжный: переписывание критерия под уже сделанную работу означает, что границы больше нет.
5.3 Шов, по которому режут
Хороший шов даёт часть, которую можно выкатить и которая кому-то полезна сама по себе:
- По слою: сначала правильная запись данных, потом отображение.
- По подмножеству данных: сначала товары со штрихкодом (3 385 из 3 412), отдельной задачей — 27 без него.
- По направлению обмена: сначала выгрузка в 1С, потом загрузка из неё.
- Диагностика перед лечением: сначала лог и отчёт, показывающие масштаб; потом фикс. Часто после первой части выясняется, что вторая нужна не в том виде, в каком задумывалась.
Плохой шов — «сделаю половину каждого»: обе половины не выкатываются, ревью невозможно, откат бессмыслен.
7. Признаки того, что границы заданы неверно изначально
Если тянет за границу постоянно, проблема обычно в самой границе.
| Признак | Что означает | Что делать |
|---|---|---|
| Критерий не проверяется командой или наблюдением | это пожелание | переформулировать до начала работы |
| В задаче союз «и» между разными результатами | это две задачи | разрезать |
| ИСКЛЮЧЕНО пусто | границу не думали, а записали | заполнить тем, что соблазнительно |
| Каждая правка тянет правку в соседнем модуле | граница прошла поперёк связности | пересобрать по слою или модулю |
| Задача звучит как «разобраться с X» | это исследование, у него другой результат | первая задача — отчёт, вторая — фикс |
| Оценка «пара часов» держится третий день | оценку делали до знания, которого не было | пересобрать оценку вслух, не молча |
Если границу задал заказчик и она прошла поперёк кода — не спорь абстрактно: покажи список файлов, который получается, и предложи другой разрез с тем же бизнес-результатом.
8. Возврат к границам после отвлечения
Дорого не само отвлечение, а возврат наугад: чаще всего после него человек продолжает не задачу, а последнее, что попалось на глаза.
9. Формулировки: границу держит произнесённый договор
Граница, оставшаяся намерением, не держит ничего. Держит фраза, сказанная вслух, с которой согласился второй человек.
9.1 Заказчику, когда просят «заодно»
- «Это отдельная правка. Сегодняшняя задача выходит вечером, эту заведу следующей и оценю к утру — или, если она важнее, поменяем местами и сегодняшняя переедет».
- «Сделать сейчас можно, но тогда правки поедут одним куском: если что-то придётся откатывать, откатится всё вместе. Разными — выкатываются независимо».
- «По деньгам: сама правка 15 минут, но с ревью выросшего диффа и риском разбора при откате выходит около полутора часов. Отдельной задачей — те же 15 минут плюс своё маленькое ревью».
9.2 Коллеге и в ревью
- «Да, там дублирование. Записал задачей, ссылка. В этом PR не трогаю, чтобы дифф остался читаемым».
- «Переименование вынес отдельным коммитом перед фиксом: поведение не менялось, тесты те же и без правок».
- «Задача оказалась больше: выкатываю часть про товары со штрихкодом, оставшиеся 27 позиций — отдельной задачей, там другая логика сопоставления».
9.3 Себе, в момент соблазна
Один вопрос: выполнится ли мой критерий готовности без этой правки? Да → «записать», руки убрал. Нет → это часть задачи: не оправдывайся, а расширь границу вслух, добавив файл в список.
Похожие навыки
Попробуйте этот навык
Зарегистрируйтесь и используйте навык «Фокус на задаче» бесплатно.