JavaRush /Курсы /Claude code /Handoff Note и Fresh Reviewer Pattern

Handoff Note и Fresh Reviewer Pattern

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

1. «Вроде готово» — это не handoff

Длинная задача ломается не при написании кода, а позже — когда нужно понять, что уже сделано, какие решения приняты, что проверено. Handoff не бюрократия, а способ сохранить смысл задачи, пока он не испарился.

Представьте: второй день чините refund-flow в AI Commerce Growth OS. Вчера вынесли логику из RefundController в RefundService, сегодня добавили тесты, заметили странный кейс с возвратом больше 1000 долларов, переключились на другой баг. Остановитесь на «логика почти вынесена, остался спорный момент» — и следующий человек заново построит всё дерево решений у себя в голове. Знание приклеилось к авторской сессии: пока диалог открыт, всё очевидно, закрыли вкладку — и половина важного была только в вашей голове. А голова не поддерживает git show.

«Вроде готово» не отвечает ни на один инженерный вопрос. Что готово? Какие файлы менялись? Что проверили? Где риск? Что дальше? Нет ответов — handoff не состоялся.

flowchart TD
    A[Writer session] --> B[HANDOFF_NOTE.md]
    A --> C[git diff]
    A --> D[Лог тестов]
    B --> E[Fresh session]
    C --> E
    D --> E
    B --> F[Человек-ревьюер]
    C --> F
    D --> F
    E --> G[Продолжение задачи]
    F --> H[Проверка и замечания]

Handoff — не один файл в вакууме, а компактный пакет смысла: HANDOFF_NOTE.md, рядом TASK_SPEC.md, актуальный diff и результаты проверок. Есть этот набор — следующий человек продолжает задачу. Есть только ваша уверенность — он начинает расследование.

2. Структура HANDOFF_NOTE.md

Записка должна быть структурированной: предсказуемый артефакт, где нужное лежит на ожидаемых местах, иначе чтение превращается в квест, только теперь в markdown. И пишется она не с нуля в последний момент, а собирается из накопленного по ходу — milestone summary, decision log, checks, риски, следующий шаг. Практичная структура для задач уровня нашего Commerce OS:

Поле Что в нём писать Зачем это нужно
Goal
Одной фразой, какой результат должен получиться Чтобы reader сразу понял, про какую задачу вообще идёт речь
Task spec
Ссылка на TASK_SPEC.md или короткое резюме scope Чтобы не вытаскивать границы задачи из памяти автора
Changed files
Какие файлы уже тронуты Чтобы быстро открыть нужные места и увидеть реальный объём работы
Decisions
Какие решения уже приняты и почему Чтобы не спорить заново с уже решёнными вещами
Assumptions
Что пока считается верным, но не доказано полностью Чтобы не путать факты и рабочие гипотезы
Evidence
Какие команды, логи, результаты подтверждают текущее состояние Чтобы handoff опирался на доказательства, а не на тон автора
Tests/checks
Что запускали и с каким результатом Чтобы следующий reader не гадал, насколько изменение вообще проверено
Known failures / Risks
Что ещё не покрыто, что тревожит, где тонкое место Чтобы незавершённость была явной, а не всплывала сюрпризом
Next step
Один конкретный следующий шаг Чтобы handoff заканчивался не туманом, а направлением движения

Принцип: handoff разделяет факты, решения, гипотезы и следующий шаг. Слиты в один абзац — читатель тратит силы на восстановление структуры, а не на работу.

Пример для refund-flow:

# HANDOFF_NOTE.md

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

## Спецификация задачи
См. TASK_SPEC.md: scope = refund-flow only, не трогать payment provider integration.

## Изменённые файлы
- src/main/java/com/acme/commerce/refund/RefundController.java
- src/main/java/com/acme/commerce/refund/RefundService.java
- src/test/java/com/acme/commerce/refund/RefundControllerTest.java

## Решения
- threshold > $100 оставлен как property, не hardcode
- controller стал тоньше, правила перенесены в service

## Тесты/проверки
- ./gradlew test --tests "*Refund*"  # 8 tests passed

## Известные риски
- кейс refund > $1000 без approval пока не покрыт тестом

## Следующий шаг
Добавить тест на > $1000 и проверить, нужен ли audit log для bypass

Заметка сохраняет не каждую мысль, а инженерную картину. И строка Known risks — не признание провала, а признак зрелости: честное «кейс > 1000 пока не покрыт» лучше, чем дать читателю наткнуться на это через сорок минут. Прозрачная незавершённость лучше красивой недосказанности.

3. Пишите для другого читателя, а не для себя

Легко написать заметку, понятную вам и бесполезную остальным: автор достраивает текст собственной памятью, у читателя такой роскоши нет. Пишите для того, кто видит только файл, diff и проверки. Главное правило: убирайте всё, что опирается только на контекст автора. Ваше «сделал основное» для другого не означает ничего; то же с «тесты ок», «почти закончил» — это разговорный шум, а не инженерная информация.

Слабая формулировка Сильная формулировка
Тесты зелёные
Запущен ./gradlew test --tests "*Refund*" — 8 tests passed
Остался один спорный кейс
Не покрыт кейс refund > $1000 без approval
Почистил контроллер
Refund decision logic вынесен из controller в RefundService
Ничего лишнего не менял
Scope сохранён: payment provider files не трогались

Разница кажется косметической, но на деле она огромная. Сильная формулировка даёт следующему читателю то, что можно проверить. Слабая просит поверить автору на слово. А весь курс, если честно, как раз и строится на привычке не верить на слово — даже если это слово сказал вчерашний вы.

Очень помогает прикладывать рядом короткий, но конкретный технический след. Например, так:

git diff --stat main...refund-refactor
# 3 files changed, 48 insertions(+), 19 deletions(-)

./gradlew test --tests "*Refund*"
# BUILD SUCCESSFUL in 8s
# 8 tests completed, 8 passed

Такие две команды уже дают новому читателю гораздо больше, чем абзац «я тут немного поправил и вроде не сломал». Особенно полезно это в задачах, которые растянуты на несколько сессий: сегодняшняя уверенность очень быстро превращается во вчерашнюю неопределённость.

И ещё один нюанс, который постоянно недооценивают. В Next step не надо писать «продолжить работу». Это не следующий шаг, это философское направление. Следующий шаг должен быть один и конкретный: «добавить тест на кейс > 1000», «сравнить diff с main и убедиться, что payment files не затронуты», «проверить, нужен ли audit log». Хороший Next step снижает цену входа в задачу почти до нуля.

4. Fresh reviewer pattern: свежий контекст

Когда вы долго ведёте одну задачу, у вас неизбежно появляется авторская слепота. Это не недостаток характера, а обычный побочный эффект длинной сессии. Вы помните, почему приняли именно такое решение, знаете, какой тупик уже пробовали, и автоматически «дочитываете» смысл там, где новый читатель увидит дыру. Именно здесь и нужен fresh reviewer pattern.

Идея очень простая. Авторская сессия делает изменение. Потом другой контекст — новая сессия Claude или живой человек — получает компактный пакет: TASK_SPEC.md, HANDOFF_NOTE.md, актуальный diff и результаты проверок. И проверяет задачу не как автор, а как читатель, который ничего не должен угадывать. Это важный сдвиг: мы перестаём спрашивать «мне кажется, всё ок?» и начинаем спрашивать «что видно по доказательствам?».

На практике свежий reviewer часто ловит три типа вещей. Во-первых, пропущенные edge cases. Во-вторых, выход за scope: например, автор «заодно» тронул файл, который не должен был трогать. В-третьих, недоказанные утверждения: тесты локально зелёные, но нужный сценарий вообще не запускался. Writer внутри своей сессии часто этого уже не замечает, потому что его внимание занято другим — историей принятых решений.

Очень удобно запускать fresh reviewer вот так:

Прочитайте TASK_SPEC.md и HANDOFF_NOTE.md.
Посмотрите текущий diff относительно main.
Проверьте только refund-flow и не меняйте файлы.
Сфокусируйтесь на:
- выходе за scope,
- пропущенных тестах,
- кейсе refund > $1000,
- несоответствии между note и реальным diff.
Верните замечания с привязкой к доказательствам.

В этом запросе есть две сильные стороны. Первая — reviewer получает scope и фокус, а не абстрактное «ну посмотри». Вторая — он работает от evidence: note, diff, tests. Это значит, что замечания можно проверить, а не спорить о них по интонации.

Представьте две ситуации. В первой авторская сессия пишет: «Всё зелёное, логика вынесена, можно мержить». Во второй fresh reviewer читает handoff, открывает RefundService, смотрит тесты и замечает: тест на сумму больше 1000 долларов отсутствует, хотя риск прямо указан в заметке. Во второй ситуации процесс сработал: handoff не спрятал незавершённость, а reviewer не сделал вид, что её нет. Именно так рождается доверие к изменениям.

Здесь полезно помнить разницу между fresh session и fresh reviewer. Fresh session можно открыть просто чтобы продолжить работу в более чистом контексте. Fresh reviewer нужен с другой целью: не продолжить, а проверить. И для этой проверки handoff особенно важен, потому что reviewer сознательно не погружается глубоко в историю автора. Он должен уметь увидеть задачу снаружи.

Именно поэтому fresh reviewer не должен получать всю переписку. Это частая ошибка. Кажется, что «чем больше контекста, тем лучше». На деле происходит обратное: новый проверяющий утаскивает к себе старые гипотезы автора и снова заражается тем же загрязнённым контекстом. Нам нужен не перенос старой усталости, а новый взгляд. Поэтому HANDOFF_NOTE.md и компактный diff полезнее огромной переписки.

5. HANDOFF_NOTE.md vs PR description и changelog

Когда вы впервые начинаете оформлять handoff, его очень легко спутать с соседними артефактами. Кажется, что PR description уже объясняет изменения, commit message уже есть, а changelog тоже что-то фиксирует. Но у этих документов разные роли. Если их смешать, каждый начинает работать хуже.

Артефакт Для кого он написан На какой вопрос отвечает
HANDOFF_NOTE.md
Для следующей session или человека, который продолжит/проверит задачу
Что сделано, что доказано, где риск и что делать дальше?
PR description
Для reviewer’а изменений как готового пакета
Что изменилось и как это проверить перед merge?
Commit message
Для истории Git
Какой логический шаг был зафиксирован этим commit?
Changelog
Для пользователя или команды релиза
Что изменилось в продукте на уровне версии/релиза?

Это очень важное различие. HANDOFF_NOTE.md живёт внутри процесса, пока задача ещё движется. PR description обычно появляется на границе готового изменения. Changelog вообще не должен объяснять, какой тест вы не успели написать для refund > 1000 — это другая плоскость разговора.

Из этой разницы следует простой практический вывод. Если задача ещё не закончена, но вы уже пишете так, как будто готовите релиз, вы теряете смысл handoff. И наоборот, если PR description превращается в дневник сомнений и незавершённых мыслей, reviewer’у будет тяжело им пользоваться. Документы должны оставаться на своих ролях.

Очень полезно держать HANDOFF_NOTE.md чуть суше и точнее, чем PR description. В нём важнее инженерная картина. Не «мы хорошо поработали и сделали код чище», а «вынесли refund decision logic, затронули три файла, запускали такие-то тесты, вот известный риск, вот следующий шаг». Это звучит менее вдохновляюще, зато действительно помогает работать.

6. Сборка handoff в Commerce OS на практике

Теперь соберём всё в один живой сценарий, чтобы handoff не остался красивой теорией. Допустим, вы ведёте задачу по AI Commerce Growth OS: нужно вынести decision logic возвратов из контроллера в сервис, не меняя API и не залезая в интеграцию с платёжным провайдером. Задача уже не помещается в один промпт, значит, без handoff она почти гарантированно начнёт разваливаться.

Сначала авторская сессия работает в своей ветке, делает первый milestone, запускает целевые тесты и фиксирует промежуточное состояние. В этот момент не нужно ждать «полной готовности». Как раз наоборот: handoff особенно полезен до полной готовности, когда уже есть сделанная часть, есть риск и понятен следующий шаг.

Например, после первого этапа у вас может получиться такой мини-ритм:

git add src/main/java/com/acme/commerce/refund/RefundController.java
git add src/main/java/com/acme/commerce/refund/RefundService.java
git add src/test/java/com/acme/commerce/refund/RefundControllerTest.java
git commit -m "Вынес refund decision logic в RefundService"

git status
# On branch refund-refactor
# working tree clean

После этого авторская сессия обновляет HANDOFF_NOTE.md, а fresh reviewer открывает задачу уже не по памяти автора, а по артефактам. Он видит scope из TASK_SPEC.md, видит, что затронут только refund-flow, видит тесты и строку про непокрытый кейс > 1000. И именно поэтому вместо расплывчатого «ну вроде мержим» появляется нормальный инженерный разговор: сначала добавим недостающий тест, потом ещё раз посмотрим на diff.

Самое ценное здесь в том, что handoff делает задачу независимой от одного носителя знания. Если автор уходит, задача не умирает. Если вы сами открываете её завтра, вам не нужно «вспоминать, что я там имел в виду». Если вы хотите посмотреть на неё свежими глазами, reviewer получает короткий и проверяемый пакет вместо десяти экранов переписки. В этот момент длинная AI-assisted задача перестаёт быть личной тайной автора и становится управляемой инженерной работой.

1
Задача
Claude code, 6 уровень, 4 лекция
Недоступна
Fresh-context чтение handoff после /clear
Fresh-context чтение handoff после /clear
1
Задача
Claude code, 6 уровень, 4 лекция
Недоступна
Подготовка HANDOFF_NOTE по входным материалам
Подготовка HANDOFF_NOTE по входным материалам
1
Опрос
Длинные задачи и Git-recovery в Claude Code, 6 уровень, 4 лекция
Недоступен
Длинные задачи и Git-recovery в Claude Code
Длинные задачи и Git-recovery в Claude Code
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ