JavaRush /Курсы /Claude code /Длинные задачи без бесконечного чата

Длинные задачи без бесконечного чата

Claude code
6 уровень , 0 лекция
Открыта

1. Длинная задача ломается не в коде, а в процессе

Длинная задача ломается не оттого, что модель «плохо кодит», а когда процесс теряет форму: контекст разрастается, гипотезы перемешиваются, вы обсуждаете три проблемы сразу, diff не читается.

Возьмём AI Commerce Growth OS. Надо вынести refund-логику из RefundController в RefundService: не сломать API, не трогать платёжного провайдера, сохранить поведение. Дайте Claude запрос «отрефактори refund-flow и сделай код нормальным» — и полезность без границ расползётся: через полчаса обсуждаете DTO, exception handler, логи и pagination в соседнем модуле. Не задача, а клубок задач.

Если работать «одним заходом» Если работать как инженерный процесс
Один большой запрос
task spec + milestones
Безымянная сессия Именованная сессия под конкретную задачу
Правки «раз уж мы тут» Жёсткий scope и запрет на unrelated work
Один коммит в конце Маленькие коммиты на границах этапов
Остановка по усталости Stop points по плану
Память только в диалоге Summary и decision log

Длинная AI-assisted задача — это не большой prompt, а маленький инженерный процесс. Не спроектируете его — задача поплывёт раньше, чем сломается код.

2. Каркас длинной задачи: spec и milestones

Чтобы задача не расползалась, ей нужен каркас на три вопроса: что делаем, чего не делаем, где останавливаемся проверять состояние. Превращайте task spec сразу в скелет процесса — цель, ограничения, деление на этапы:

# TASK_SPEC: refund-flow refactor

## Цель
Вынести refund decision logic из RefundController в RefundService.

## Область изменений
Только refund-flow.

## Не-цели
Не менять payment provider integration.
Не менять публичный API.
Не менять схему БД.

## Ограничения
Сохранить текущее поведение и зелёные тесты.

## Майлстоуны
M1 — зафиксировать текущее поведение тестами
M2 — вынести логику в RefundService
M3 — сделать контроллер тонким и перепроверить интеграционные тесты

## Точки остановки
После каждого milestone: summary + checks + commit

Задача получила форму: Claude не блуждает «улучшу ещё пару мест», а идёт по коридору.

flowchart TD
    A[TASK_SPEC] --> B[Named session]
    B --> C[Milestone 1]
    C --> D[Summary + checks + small commit]
    D --> E[Milestone 2]
    E --> F[Summary + checks + small commit]
    F --> G[Milestone 3]
    G --> H[Stop point / finish]

Milestones делают задачу переносимой и проверяемой. Без них непонятно, где она, и любая пауза становится болью.

3. Именованная сессия: у задачи должно быть имя

Задача живёт дольше десяти минут — безымянная сессия работает против вас. Скоро у вас «та длинная про refunds», «ещё одна похожая, но там тесты» и «какая-то, где Claude предлагал util-класс». Память подводит уже не модель, а вас.

Дайте задаче имя, совпадающее с workstream, branch и смыслом task spec:

Что именуем Пример
Задача
refund-refactor
Branch
feature/refund-refactor
Session
refund-refactor

Тогда у вас не три сущности, а один маршрут: задача, ветка, сессия, изменения. До первого перерыва — мелочь, после первого обеда — спасение.

Переоткрытие:

# точное имя команды и флага зависит от версии Claude Code
claude --resume refund-refactor

Важна не команда, а привычка: сессия привязана к задаче, а не висит как «ещё один чат». Название вроде new chat, session-12 или test2-final-final — сигнал, что процесс уходит в хаос.

4. Milestone summary и decision log

Истории диалога мало: память выносят наружу короткими выводами. Milestone summary — «где мы сейчас», decision log — «какие решения приняты, чтобы через полчаса не спорить заново».

Минимальный summary после этапа:

## Summary майлстоуна: M1

Готово:
- добавлены тесты на текущее refund-поведение
- зафиксированы кейсы partial refund и approval > $100

Открытые вопросы:
- кейс refund > $1000 пока не покрыт

Риски:
- integration path с payment provider ещё не перепроверен

Дальше:
- вынести decision logic в RefundService

Decision log:

## Лог решений
- threshold $100 оставляем в configuration property
- payment provider integration не трогаем в этом refactor
- не переносим exception mapping в эту же задачу

Жить в одном «правильном» файле эти заметки не обязаны: рядом с задачей, в заметке к ветке, в markdown. Из них собирается handoff для fresh session или reviewer.

Без журнала сессия живёт в режиме «кажется, мы это уже обсуждали»: Claude снова предлагает отвергнутый вариант, а вы вспоминаете об этом через пару сообщений. Хороший summary — снимок состояния, не отчёт для начальства.

5. Stop points: останавливаться по плану

Задачи портятся от неудачной остановки. Самый частый stop point: «Ладно, устал, завтра продолжу». Усталость — плохой критерий: задача брошена в случайной точке.

Хороший stop point — конец осмысленного куска: добавили characterization tests; вынесли логику в сервис и прогнали проверки; сделали контроллер тонким и посмотрели diff. Это место, где задачу можно безопасно передать даже себе будущему: ясно, что сделано, что нет, какие проверки запускались, какой шаг следующий.

Маленький commit на границе этапа снижает цену продолжения:

git commit -m "test(refund): characterize approval rules"
git commit -m "refactor(refund): extract RefundService"

Summary объясняет смысл этапа, commit фиксирует состояние файлов. Только commit — не видно решений за ним; только текст — нечего продолжать.

И ещё: stop point не даёт тащить постороннее. «Сейчас бы заодно поправить формат логов» — спросите: это часть milestone или другая история? В девяти случаях из десяти — другая.

6. Context rot: когда сессия помнит лишнее

Загрязнение контекста вы уже видели на коротких задачах. На длинной оно коварнее: контекст не просто переполняется — он стареет. Это context rot: сессия тащит старые гипотезы и отвергнутые идеи как живые.

Вы решили не выносить refund-логику в RefundUtils — размоет границы ответственности. Через сорок минут контекст разросся, и Claude снова: «Возможно, стоит вынести общую логику в utility class». Не назло — старая гипотеза сидит рядом с новыми данными.

Мини-сценка:

Вы: utility class не подходит, оставляем сервисный слой
Claude: понял, идём через RefundService
...
через 30 минут
Claude: чтобы уменьшить дублирование, можно вынести логику в RefundUtils

Проблема не в ответе — сессия начала гнить. Другие признаки: ходит кругами по отвергнутым вариантам, смешивает подходы, ссылается на устаревшие assumptions, лезет в файлы вне scope.

Не дожимайте. Остановитесь, соберите summary, зафиксируйте решения, продолжайте из чистого состояния. Распознать context rot — не слабость, а дисциплина.

7. Два режима задачи: пошаговый и goal-driven

Каркас есть — как вести задачу? Два режима: пошаговый и goal-driven (работа до формально проверяемого условия завершения). Вопрос — какой безопаснее.

Сравним:

Пошаговый режим Goal-driven режим
После каждого шага вы подтверждаете, что делать дальше Claude идёт несколько ходов подряд до достижения условия завершения
Лучше для рискованных изменений Лучше для хорошо ограниченных задач
Подходит, когда нужно много человеческих решений Подходит, когда есть детерминированные проверки
Медленнее, но прозрачнее Быстрее, но требует хорошего verification harness

Пошаговый — классика для чувствительных задач: шаг, diff, проверки, решение, дальше. Особенно где затронуты деньги, внешние контракты или форма решения ещё не ясна.

Goal-driven хорош только когда конец проверяет машина — есть machine-checkable termination condition без ваших субъективных оценок.

Плохие условия:

Плохая формулировка Почему она плохая
«Сделай аккуратно» Машина не знает, что такое «аккуратно»
«Когда станет лучше» Это субъективно
«Когда код будет чистым» Тоже субъективно

Хорошие условия:

Хорошая формулировка Почему она хорошая
./gradlew test
завершается без ошибок
Проверяется машинно
./gradlew build
зелёный
Проверяется машинно
Нужные тесты проходят Проверяется машинно

Пример в task spec может выглядеть так:

## Условие завершения
Задача считается завершённой, когда:
- RefundControllerTest проходит
- RefundServiceTest проходит
- ./gradlew test завершается с code 0
- публичный API refund endpoint не изменён

Здесь есть тонкий, но важный нюанс. Goal-driven режим безопасен только при детерминированной верификации. Если у вас нет надёжных тестов, если проверка субъективна, если задача про «на глаз стало удобнее», запускать такой режим опасно. Это уже не инженерный автопилот, а игра в «надеюсь, мы где-нибудь вовремя остановимся». А надежда, как известно, не входит в официальный стек quality assurance.

8. Сквозной пример: refund-flow в Commerce OS

Чтобы всё это не висело в воздухе, давайте соберём один цельный сценарий. Допустим, в Commerce OS у нас есть задача: refactor refund-flow так, чтобы decision logic ушла из контроллера в сервисный слой, а поведение осталось прежним. Задача не на пять минут, но и не на две недели. Классический кандидат на аккуратную длинную сессию.

Скелет может быть таким:

# TASK_SPEC: refund-flow refactor

Цель:
Вынести refund decision logic из RefundController в RefundService.

Область:
Только refund-flow.

Ограничения:
Не менять API, не трогать payment provider integration, сохранить tests green.

Майлстоуны:
M1 — characterization tests
M2 — RefundService extraction
M3 — controller cleanup + verification

Точки остановки:
После каждого milestone: summary + checks + commit

Сессию мы называем refund-refactor. Branch — feature/refund-refactor. После первого этапа фиксируем короткий summary:

## Summary майлстоуна: M1
Готово:
- добавлены тесты на approval threshold
- partial refund поведение зафиксировано

Решения:
- threshold не переносим в БД
- payment integration вне scope

Дальше:
- выделить RefundService без изменения API

Дальше, на втором этапе, вам уже не нужно заново вспоминать, почему threshold не ушёл в БД и зачем мы не трогаем интеграцию. Решение записано. Контекст не обязан таскать это только в своей истории.

Если на втором этапе Claude начинает снова предлагать utility class или лезть в PaymentGatewayClient, вы не спорите бесконечно. Вы видите: задача начинает уходить из рамки. Значит, пора остановиться, посмотреть summary и вернуть процесс в границы milestone. А если задача достаточно формализована и тесты надёжны, можно задать машинно проверяемое условие завершения именно для этого этапа: например, все refund-тесты зелёные и билд не падает.

В таком режиме длинная задача перестаёт быть бесконечным чатом, который страшно закрыть. Она превращается в последовательность небольших, понятных состояний. У каждого состояния есть имя, границы, short summary, зафиксированные решения и ясный следующий шаг. А это уже совсем другой уровень контроля. И, что особенно приятно, здесь Claude действительно начинает усиливать разработчика, а не тащить его за собой в хаос из «ещё одной хорошей идеи».

1
Задача
Claude code, 6 уровень, 0 лекция
Недоступна
Осмысленное имя сессии и status snapshot
Осмысленное имя сессии и status snapshot
1
Задача
Claude code, 6 уровень, 0 лекция
Недоступна
Терминальный baseline для длинной задачи
Терминальный baseline для длинной задачи
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ