1. «Готово» от Claude — ещё не финал
Claude пишет: задача завершена, тесты предложены. Само по себе это слово не значит почти ничего — проверять всё равно вам.
Цели и критериев приёмки мало. Нужны две опоры, заданные заранее. План проверки — что и как проверяем. Готовность задачи — чек-лист завершённости. Смешаете — получите «вроде что-то проверили» без понимания, хватает ли для приёмки.
2. План проверки и готовность задачи — это не одно и то же
Термины похожи на слух, поэтому их путают. Различие принципиальное. План проверки — набор сигналов, которыми доказываем результат. Готовность задачи — весь набор условий приёмки: не только тесты, но и scope, понятный diff, документация, риски, человеческий review.
| Что сравниваем | План проверки | Готовность задачи |
|---|---|---|
| Главный вопрос | Как проверяем? | Когда считаем завершённым? |
| Фокус | Команды, тесты, логи, expected output | Полная готовность задачи к приёмке |
| Когда появляется | До implementation | Тоже до implementation |
| Пример | ./gradlew test, smoke-check API, проверка логов | diff в scope, тесты зелёные, docs обновлены, risks noted, human reviewed |
План — маршрут, готовность — финишная рамка. Маршрут пройден, но задели пять файлов вне scope — задача не done.
3. План проверки пишется до кода
Частая ошибка: пусть Claude сначала напишет, а потом посмотрим, как проверять. Тогда проверка подгоняется под готовый результат. Открыли diff после фикса бага с двойным возвратом денег в Commerce OS: «А что теперь проверять?» — и подстроили план под то, что получилось.
План, написанный до implementation, защищает от самообмана. Сигналы заданы заранее: не совпали — «готово» сказать нельзя, даже если 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. Готовность возвращает разработку из «в целом ok» в «есть понятные условия завершённости».
Машинно-проверяемый набор — 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 задачи
Ещё одна недооценённая идея — 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 зелёные — человеческий review всё равно часть done. Не потому, что AI «плохой», а потому, что diff нужно прочитать и связать с контекстом проекта.
Только человек замечает: «тест зелёный, но это не тот слой», «баг исправлен, но метод стал хуже читаться и задел соседний сценарий», «почему поменялся сериализатор, если задача про refund?». Claude часть увидит, но финальная ответственность — за человеком.
Короткая формула:
Claude может помочь написать код, тесты и даже план проверки. Но сказать «done» по-настоящему может только человек, который прочитал diff и принял риск.
Human review в готовности — не формальность, а нормальная часть инженерного цикла.
13. Маленькая рабочая схема на память
flowchart TD
A[Критерии приёмки] --> B[План проверки]
B --> C[Implementation]
C --> D[Checks and tests]
D --> E[Готовность задачи]
E --> F[Human review and decision]
Схема не даёт перескочить ступени — особенно любимую «сразу в implementation». Разберёмся и так, но грустнее и дороже.
14. Подводим итоги
Оформляя задачу для Claude, задайте себе три вопроса. Что должно стать правдой в конце? — критерии приёмки. Как я это докажу? — план проверки. По каким признакам задача завершена целиком? — готовность задачи.
Есть ответы — implementation идёт спокойнее. Claude не работает в тумане, а вы не убеждаете себя, что зелёный тест равен готовой задаче. Шаг из режима «вроде работает» в нормальную инженерию.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ