1. «Начебто готово» — це не handoff
Довга задача ламається не під час написання коду, а пізніше — коли потрібно зрозуміти, що вже зроблено, які рішення прийняті, що перевірено. Handoff — не бюрократія, а спосіб зберегти зміст задачі, поки він не випарувався.
Уявіть: другий день виправляєте refund-flow в AI Commerce Growth OS. Учора винесли логіку з RefundController у RefundService, сьогодні додали тести, помітили дивний кейс із поверненням понад 1000 доларів, перемкнулися на інший баг. Зупиніться на «логіку майже винесли, лишився спірний момент» — і наступна людина заново побудує все дерево рішень у себе в голові. Знання приклеїлося до авторської сесії: поки діалог відкрито, все очевидно, закрили вкладку — і половина важливого була лише у вашій голові. А голова не підтримує git show.
«Начебто готово» не відповідає на жодне інженерне запитання. Що готово? Які файли змінювалися? Що перевірили? Де ризик? Що далі? Немає відповідей — handoff не відбувся.
flowchart TD
A[Сесія автора] --> B[HANDOFF_NOTE.md]
A --> C[git diff]
A --> D[Лог тестів]
B --> E[Свіжа сесія]
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:
| Поле | Що в ньому писати | Навіщо це потрібно |
|---|---|---|
|
Однією фразою, який результат має вийти | Щоб читач одразу зрозумів, про яку задачу взагалі йдеться |
|
Посилання на TASK_SPEC.md або коротке резюме scope | Щоб не витягувати межі задачі з памʼяті автора |
|
Які файли вже зачеплено | Щоб швидко відкрити потрібні місця й побачити реальний обсяг роботи |
|
Які рішення вже прийнято і чому | Щоб не сперечатися заново з уже розвʼязаними речами |
|
Що поки вважається правильним, але не доведено повністю | Щоб не плутати факти і робочі гіпотези |
|
Які команди, логи, результати підтверджують поточний стан | Щоб handoff спирався на докази, а не на тон автора |
|
Що запускали і з яким результатом | Щоб наступний читач не гадав, наскільки зміну взагалі перевірено |
|
Що ще не покрито, що турбує, де тонке місце | Щоб незавершеність була явною, а не спливала сюрпризом |
|
Один конкретний наступний крок | Щоб 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 тестів пройшли
## Відомі ризики
- кейс refund > $1000 без approval поки що не покрито тестом
## Наступний крок
Додати тест на > $1000 і перевірити, чи потрібен audit log для bypass
Записка зберігає не кожну думку, а інженерну картину. І рядок Відомі ризики — не визнання провалу, а ознака зрілості: чесне «кейс > 1000 поки не покрито» краще, ніж дати читачеві наштовхнутися на це через сорок хвилин. Прозора незавершеність краща за красиву недомовленість.
3. Пишіть для іншого читача, а не для себе
Легко написати записку, зрозумілу вам і марну для інших: автор добудовує текст власною памʼяттю, у читача такої розкоші немає. Пишіть для того, хто бачить лише файл, diff і перевірки. Головне правило: прибирайте все, що спирається лише на контекст автора. Ваше «зробив основне» для іншого не означає нічого; те саме з «тести ок», «майже закінчив» — це розмовний шум, а не інженерна інформація.
| Слабке формулювання | Сильне формулювання |
|---|---|
|
|
|
|
|
|
|
|
Різниця здається косметичною, але насправді вона величезна. Сильне формулювання дає наступному читачеві те, що можна перевірити. Слабке просить повірити авторові на слово. А весь курс, якщо чесно, якраз і будується на звичці не вірити на слово — навіть якщо це слово сказали вчорашні ви.
Дуже допомагає додавати поруч короткий, але конкретний технічний слід. Наприклад, так:
git diff --stat main...refund-refactor
# 3 файли змінено, 48 вставок(+), 19 вилучень(-)
./gradlew test --tests "*Refund*"
# Збірка успішна за 8 с
# 8 тестів виконано, 8 пройшли
Ці дві команди вже дають новому читачеві набагато більше, ніж абзац «я тут трохи поправив і начебто не зламав». Особливо корисно це в задачах, які розтягнуті на кілька сесій: сьогоднішня впевненість дуже швидко перетворюється на вчорашню невизначеність.
І ще один нюанс, який постійно недооцінюють. У 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 і результати перевірок. І перевіряє задачу не як автор, а як читач, який нічого не має вгадувати. Це важливий зсув: ми перестаємо питати «мені здається, все ок?» і починаємо питати «що видно з доказів?».
На практиці свіжий ревʼюер часто ловить три типи речей. По-перше, пропущені 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 теж щось фіксує. Але в цих документів різні ролі. Якщо їх змішати, кожен починає працювати гірше.
| Артефакт | Для кого він написаний | На яке запитання відповідає |
|---|---|---|
|
Для наступної сесії або людини, яка продовжить/перевірить задачу | |
|
Для ревʼюера змін як готового пакета | |
|
Для історії Git | |
|
Для користувача або команди релізу | |
Це дуже важлива різниця. 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
# На гілці refund-refactor
# робоче дерево чисте
Після цього авторська сесія оновлює HANDOFF_NOTE.md, а fresh reviewer відкриває задачу вже не за памʼяттю автора, а за артефактами. Він бачить scope із TASK_SPEC.md, бачить, що зачеплено лише refund-flow, бачить тести й рядок про непокритий кейс > 1000. І саме тому замість розпливчастого «ну начебто мерджимо» з’являється нормальна інженерна розмова: спершу додамо відсутній тест, потім ще раз подивимося на diff.
Найцінніше тут у тому, що handoff робить задачу незалежною від одного носія знання. Якщо автор іде, задача не помирає. Якщо ви самі відкриваєте її завтра, вам не потрібно «згадувати, що я там мав на увазі». Якщо ви хочете подивитися на неї свіжими очима, reviewer отримує короткий і перевірний пакет замість десяти екранів переписки. У цей момент довга AI-assisted задача перестає бути особистою таємницею автора і стає керованою інженерною роботою.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ