1. «Готово» від Claude — ще не фінал
Claude пише: задача завершена, тести запропоновано. Саме по собі це слово майже нічого не означає — перевіряти все одно вам.
Цілей і критеріїв приймання замало. Потрібні дві опори, задані заздалегідь. План перевірки — що і як перевіряємо. Готовність задачі — чекліст завершеності. Змішаєте їх — отримаєте «нібито щось перевірили» без розуміння, чи цього досить для приймання.
2. План перевірки та готовність задачі — це не одне й те саме
Терміни на слух схожі, тому їх плутають. Різниця принципова. План перевірки — набір сигналів, якими доводимо результат. Готовність задачі — увесь набір умов приймання: не лише тести, а й scope, зрозумілий diff, документація, ризики, людське ревʼю.
| Що порівнюємо | План перевірки | Готовність задачі |
|---|---|---|
| Головне питання | Як перевіряємо? | Коли вважаємо завершеним? |
| Фокус | Команди, тести, логи, expected output | Повна готовність задачі до приймання |
| Коли зʼявляється | До реалізації | Також до реалізації |
| Приклад | ./gradlew test, smoke-check API, перевірка логів | diff у межах scope, тести зелені, docs оновлено, risks noted, human reviewed |
План — маршрут, готовність — фінішна рамка. Маршрут пройдено, але ви зачепили пʼять файлів поза scope — задача не done.
3. План перевірки пишеться до коду
Часта помилка: нехай Claude спочатку напише, а потім подивимося, як перевіряти. Тоді перевірка підганяється під готовий результат. Відкрили diff після фіксу бага з подвійним поверненням коштів у Commerce OS: «А що тепер перевіряти?» — і підлаштували план під те, що вийшло.
План, написаний до реалізації, захищає від самообману. Сигнали задані заздалегідь: не збіглися — «готово» сказати не можна, навіть якщо diff солідний і Claude впевнений у собі. А впевнений він буває і тоді, коли проєкт уже зламано.
Щоб план не виродився в список команд «за звичкою», розкладіть кожен критерій приймання на спостережуваний сигнал, перевірку та fail condition.
| Критерій | Який сигнал його підтверджує | Чим перевіряємо | Що вважаємо fail condition |
|---|---|---|---|
| Один refund створюється на один запит | У системі зʼявляється лише один refund/event на один idempotency key | regression test + integration/smoke-check на повторний запит | зʼявляється другий refund або другий refund.created |
| Retry не призводить до повторного refund | Повторний виклик повертає безпечний результат без нової записи | test на retry-сценарій і перегляд логів | retry створює новий запис або повторно викликає зовнішню оплату |
| Public API /api/refunds не змінюється | Схема відповіді та обовʼязкові поля залишаються незмінними | smoke-check або API test на поточний контракт | у відповіді змінюється структура або семантика полів |
Спочатку — що має стати правдою, потім — перевірний сигнал, і лише потім команди, тести та ручні перевірки.
4. L1 verification — перший шар перевірки
Verification побудовано шарами. Сьогодні — найнижчий, L1: план перевірки однієї задачі. Не CI, не стратегія тестування команди.
Задача: виправити баг у RefundService, через який один запит на refund іноді створює два повернення. На L1 ви не будуєте архітектуру тестування — фіксуєте приземлене:
- які команди запустити;
- який тест має зʼявитися або змінитися;
- яку відповідь API очікуємо;
- який лог має зникнути або зʼявитися;
- що робити, якщо одна з перевірок впала.
L1 — шар «як доведемо, що виконано саме цю задачу». Без нього решта — театр.
5. Приклад плану перевірки для Commerce OS
Фрагмент TASK_SPEC.md для наскрізного проєкту:
## План перевірки (L1)
Команди:
- `./gradlew :billing:test --tests RefundServiceTest`
- `./gradlew :billing:integrationTest`
Перевірки:
- додати regression test `refund_is_idempotent_under_retry()`
- тест має падати до виправлення і проходити після
Очікуваний результат:
- один refund на один запит
- public API `/api/refunds` не змінюється
Якщо перевірка не пройшла:
- не робити merge
- повернутися до аналізу логів і retry-логіки
Зрозуміло, що запускати, що дивитися, що вважати успіхом. Детальніше:
## План перевірки (L1)
Команди:
- `./gradlew :billing:test --tests RefundServiceTest` # локальний unit/regression
- `./gradlew :billing:integrationTest` # перевірка інтеграції
- `curl -X POST /api/refunds -d @repro/refund.json` # ручний smoke-check
Логи:
- не має бути повторного `refund.created`
- retry без `Idempotency-Key` не допускається
Очікуваний результат:
- один refund event на один запит
- API response schema без змін
План не зводиться до тестів: сюди входять ручні smoke-check, перевірка логів, контроль сумісності API.
6. Готовність задачі — момент завершеності
Другий шар ширший: питання не «що прогнали», а «чи завершено задачу цілком».
## Готовність задачі
- [ ] diff зачіпає лише refund-related файли та тести
- [ ] немає випадкових formatting-змін поза scope
- [ ] regression test падає до виправлення і проходить після
- [ ] relevant tests зелені
- [ ] public API не змінився
- [ ] risks і limitations записано
- [ ] diff прочитано людиною до merge
Частину плану можна чесно виконати й не дійти до done. Тести зелені, але diff захопив три зайві файли. Або забули описати limitation. Або змінився public API. Готовність повертає розробку з «загалом ок» у «є зрозумілі умови завершеності».
Машинно-перевірний набір — tests проходять, build зелений, lint зелений, diff у погоджених файлах — стає прямим входом для режиму «за ціллю», який ми вводимо як ментальну модель на рівні 6. Умова фінішу: «усі машинно-перевірні пункти дають true», і Claude крутить цикл «правка → запуск перевірок → правка» без вашого підтвердження на кожному кроці. Далі в курсі той самий підхід іде до TDD-циклу, до керованої реалізації кроків плану та до пілотної міграції — про це в наступних рівнях.
Субʼєктивні пункти — «UX ок», «текст зрозумілий», «архітектура чистіша» — для автоциклу не годяться, рішення за людиною. Діліть готовність на два шари: машинна йде в автоцикл, людська залишається точкою схвалення. Реалізація — інтерактивний запит, slash-команда на кшталт /goal, цикл через claude -p — залежить від версії. Важлива модель: опишіть фініш так, щоб машина сама перевірила його досягнення.
7. Не заходьте в крайнощі
Інша крайність: документ на два екрани з CI, релізом, безпекою, деплоєм, performance review.
Тримайте межу. Готовність задачі — приймання на рівні задачі, а не весь процес команди. Вона не замінює quality gates, release checklist, production policy. Її завдання скромніше: зрозуміти, чи завершена ця задача в поточному scope.
Занадто велика — нею перестануть користуватися. Занадто маленька — втратить сенс.
8. Аудит відтворюваності задачі
Ще одна недооцінена ідея — reproducibility audit. Якщо завтра колега відкриє задачу, чи зрозуміє він, що зроблено, як перевірялося і чому done?
У розробці з AI це особливо важливо. Історія роботи з Claude — гіпотези, логи, що спочатку не працювало — залишається у вашій голові. Інша людина бачить лише артефакти: TASK_SPEC.md, diff, tests, опис PR.
Тому добра готовність включає відтворюваність. Які команди запускалися? Який тест став regression test? Що залишилося ризиком? Де обмеження? Інакше впевненість живе лише у вашій голові.
9. Повний фрагмент TASK_SPEC.md
Верхня частина TASK_SPEC.md з goal, scope, constraints і evidence уже є. Додаємо три бракуючі блоки:
## Критерії приймання
- один refund створюється на один запит
- retry не призводить до повторного refund
- public API `/api/refunds` не змінюється
## План перевірки (L1)
Команди:
- `./gradlew :billing:test --tests RefundServiceTest`
- `./gradlew :billing:integrationTest`
Перевірки:
- додати regression test `refund_is_idempotent_under_retry()`
- перевірити, що до виправлення тест падає, після виправлення проходить
- виконати ручний smoke-check через test payload
## Готовність задачі
- diff у межах scope
- немає unrelated файлів
- tests зелені
- API сумісний
- risks і limitations записано
- human review виконано
Критерії приймання — що має стати правдою; план перевірки — як перевірити; готовність задачі — коли вважаємо завершеним. Людині це дає контроль, Claude — рамку, з якої не поїдеш убік.
10. Невеликий Java-приклад перевірки
Приклад поза markdown-артефактами. Метод не має допускати повторний refund для одного запиту.
import java.util.HashSet;
import java.util.Set;
public class Demo {
public static void main(String[] args) {
Set<String> processedRefunds = new HashSet<>();
boolean created = processedRefunds.add("refund-123");
System.out.println(created); // true
created = processedRefunds.add("refund-123");
System.out.println(created); // false
}
}
Принцип ідемпотентності: перший раз операція проходить, другий — ні. Але це ілюстрація поведінки, не план перевірки. План починається там, де ви описуєте, який тест це доведе, в якому модулі він лежить, що відбувається до виправлення і після.
Код — не доказ. Код — матеріал, з якого доказ збирають.
11. Claude у verification без права на «done»
Claude корисний за вузької задачі. Замість «перевір, чи все ок» — конкретний запит.
Склади план перевірки для цієї задачі.
Не змінюй код.
Поверни:
1) які команди запускати,
2) які tests додати або оновити,
3) які expected outputs перевірити,
4) що вважати fail condition.
Або так:
Перевір мою готовність задачі для bugfix у RefundService.
Скажи, чого бракує для task-level приймання.
Не пропонуй CI/release-процес, лише task-level done.
Claude не стверджує, що задача завершена, — він допомагає спроєктувати рамку перевірки. Надійніше, ніж «перевір усе» з надією, що модель не забула про scope, compatibility і risks.
12. Human review залишається обовʼязковим
План прекрасний, готовність акуратна, tests зелені — людське ревʼю все одно частина done. Не тому, що AI «поганий», а тому, що diff потрібно прочитати й повʼязати з контекстом проєкту.
Лише людина помічає: «тест зелений, але це не той шар», «баг виправлено, але метод став гірше читатися й зачепив сусідній сценарій», «чому змінився серіалізатор, якщо задача про refund?». Claude частину побачить, але фінальна відповідальність — за людиною.
Коротка формула:
Claude може допомогти написати код, тести й навіть план перевірки. Але сказати «done» по-справжньому може лише людина, яка прочитала diff і прийняла ризик.
Human review у готовності — не формальність, а нормальна частина інженерного циклу.
13. Маленька робоча схема для памʼяті
flowchart TD
A[Критерії приймання] --> B[План перевірки]
B --> C[Реалізація]
C --> D[Перевірки та тести]
D --> E[Готовність задачі]
E --> F[Людське ревʼю та рішення]
Схема не дає перестрибнути щаблі — особливо улюблений «одразу в реалізацію». Розберемося і так, але сумніше й дорожче.
14. Підбиваємо підсумки
Оформлюючи задачу для Claude, поставте собі три питання. Що має стати правдою наприкінці? — критерії приймання. Як я це доведу? — план перевірки. За якими ознаками задача завершена цілком? — готовність задачі.
Є відповіді — реалізація йде спокійніше. Claude не працює в тумані, а ви не переконуєте себе, що зелений тест дорівнює готовій задачі. Крок із режиму «нібито працює» у нормальну інженерію.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ