
Совет — зная это, вы уже можете командовать
Четыре фразы — это всё.
Агенту: “Создай Hurl-тест” ИИ напишет контракт, проверяющий правильность работы функции. Plain text, который можно прочитать без навыков программирования.
Агенту: “Добавь эту функцию. Но существующие Hurl-тесты должны проходить” Эта одна фраза предотвращает дрифт. Если ИИ при добавлении новой функции сломает существующую — Hurl сообщит красным текстом.
Агенту: “Закоммить” Сохранение рабочего состояния. Как точка сохранения в игре. Если следующая задача провалится — возврат сюда.
Агенту: “Откати” Возврат к последней точке сохранения. Восстановление того, что ИИ сломал.
Паттерн этих четырёх фраз
Функция готова → “Создай Hurl-тест” → Проверка прохождения → “Закоммить” → Следующая функция → “Существующие Hurl должны проходить” → При проблеме “Откати”
Это храповик. Шестерёнка, идущая только вперёд. Будь функций 5 или 50 — существующие не ломаются.
Почему это работает?
В уроке 2 мы узнали: дайте ИИ мнение — получите лесть, дайте факт — получите исправление. То, что возвращает Hurl — не мнение, а факт. “test failed: status 401, expected 200” — здесь нечему льстить.
Быстрый старт
Создайте один Hurl-тест для приложения задач из практики урока 2. Это займёт 3 минуты.
Агенту: “Напиши Hurl-тест, проверяющий правильность работы текущей функции добавления задач”
ИИ создаст файл .hurl.
Агенту: “Запусти Hurl-тест”
Если прошёл — зелёный. Теперь намеренно сломаем.
Агенту: “Переименуй id в todo_id в ответе API добавления задач”
Агенту: “Запусти Hurl-тест”
Красный текст — провал. Это обнаружение дрифта.
Агенту: “Откати”
Снова зелёный. Вот суть храповика.
Почему нужно командовать именно так
В уроке 2 мы увидели проблемы: логический дрифт, потеря контекста, предвзятость лести. После 5 функций существующие ломаются, а ИИ ложно заявляет “всё работает”.
В этом уроке мы изучим три инструмента для предотвращения. Все они десятилетиями используются инженерами. Не нужно уметь читать код. ИИ пишет и запускает. Вам достаточно спросить: “Прошло?”
Роли трёх инструментов:
| Инструмент | Аналогия | Что делает |
|---|---|---|
| Hurl | Контракт | Объявляет “эта функция должна работать так” |
| Git | Точка сохранения | Гарантирует “можно вернуться к этому моменту” |
| CI/CD | Автоматическая камера наблюдения | Механизирует “проверяется каждый раз автоматически” |
Hurl — объявление API-контракта в plain text
Что такое Hurl
Hurl — это файл, описывающий “как должен работать этот API”.
По аналогии с игрой: в RPG покупка зелья у NPC имеет правило “1 зелье → -50 золота, +100 здоровья”. Hurl проверяет, что это правило не изменилось после патча.
Реальный файл Hurl:
# Добавление задачи
POST http://localhost:8080/api/todos
{
"title": "Купить молоко",
"priority": "high"
}
HTTP 201
[Asserts]
jsonpath "$.id" exists
jsonpath "$.title" == "Купить молоко"
jsonpath "$.priority" == "high"
jsonpath "$.completed" == false
Читается даже без навыков программирования:
- POST — запрос “добавь” серверу
- http://localhost:8080/api/todos — адрес списка задач
- { “title”: “Купить молоко” } — отправляем такие данные
- HTTP 201 — при успехе должен прийти ответ 201
- jsonpath “$.title” == “Купить молоко” — в ответе должно быть “Купить молоко”
Это контракт. “При добавлении задачи приходит 201, название и приоритет возвращаются как есть.” Если контракт нарушен — Hurl сообщает красным текстом.
Ещё один пример:
# Доступ без авторизации — отказ
GET http://localhost:8080/api/todos
HTTP 401
“При доступе к списку задач без логина должен прийти 401 (требуется аутентификация).” Это тоже контракт. Если ИИ “наведёт порядок” в коде авторизации и сломает это правило — Hurl поймает мгновенно.
Почему Hurl — отличие от юнит-тестов
“Инструментов тестирования много, почему именно Hurl?” Для вайб-кодера есть особая причина.
Юнит-тесты проверяют внутренние функции кода. Аналогия с автомобилем: юнит-тест — разборка и проверка каждой детали двигателя, Hurl — дорожные испытания. Если изменилось имя функции, ломается и тест, и при рефакторинге ИИ должен менять оба. Если дать ИИ право менять и код, и тесты, ИИ подгонит тесты под код. Тесты проходят, но изначальное правило исчезло.
Hurl — иначе. Он проверяет на входе. Отправляет запрос, проверяет ответ. Не знает внутреннюю структуру кода. Как бы ИИ ни менял код — если наблюдаемое поведение такое же, тест проходит, если другое — провал.
| Юнит-тесты | Hurl | |
|---|---|---|
| Аналогия | Разборка деталей двигателя | Дорожные испытания |
| Если ИИ меняет код | Тест тоже может измениться | Тест остаётся, проверяется только результат |
| Сложность чтения | Нужно знать код | Читается как обычный текст |
| Обнаружение дрифта | Если ИИ изменит и тест — пропустит | Независим от кода, обнаруживает естественно |
Hurl проверяет не код, а поведение. Код ИИ может менять свободно. Поведение меняться не должно. Это различие — ключ к обнаружению дрифта.
Почему это эффективно — доказано исследованиями
В уроке 2 мы узнали о предвзятости лести. Совет “пиши тесты” тоже зависит от формулировки.
Исследование TDAD (Test-Driven AI Development, 2026) точно это проверило. ИИ исправлял баги при разных условиях тестирования:
| Условие | Регрессия (% поломки существующих функций) |
|---|---|
| Базовое (без указаний по тестам) | 6,08% |
| Процедурное указание “делай TDD” | 9,94% (ухудшение!) |
| Предоставление файла затронутого теста в контексте | 1,82% (снижение на 70%) |
Удивительный результат. “Делай TDD” — ухудшает. ИИ путается, пытаясь следовать процедурному указанию. Но “этот тестовый файл должен проходить” — конкретный контекст — снижает регрессию на 70%.
Разница ясна:
- “Разрабатывай с тестами” → процедурное указание → ИИ путается
- “Этот Hurl-файл должен проходить” → конкретный контракт → регрессия -70%
Не указание метода, а контракт — что должно проходить. Именно об этом “фраза 3” выше.
Git — точка сохранения с возможностью отката
Что такое Git
В играх делают сохранения. Перед боссом — сохранение, проиграли — загрузка.
Git — это функция сохранения для кода. “Сейчас всё работает” → сохранение (коммит). Следующая задача провалилась → возврат к предыдущему сохранению.
Вайб-кодинг без Git:
Функция 1 → работает
Функция 2 → работает
Функция 3 → функция 1 сломалась!
→ Хочу откатить... а какое было состояние функции 2?
→ ИИ: "вернуть к тому, что было" → ИИ не знает, что было "то"
→ Начинаем сначала
С Git:
Функция 1 → работает → коммит (сохранение 1)
Функция 2 → работает → коммит (сохранение 2)
Функция 3 → функция 1 сломалась!
→ "Вернись к сохранению 2" → функции 1 и 2 работают
→ Пробуем функцию 3 другим способом
Git: достаточно двух слов
Не нужно учить десятки команд Git. Вайб-кодеру нужны две вещи.
“Закоммить” — сохранить текущее состояние
"Закоммить текущее состояние. Сообщение — 'Функция добавления задач готова'"
“Откати” — вернуться к предыдущему состоянию
"Откати к последнему коммиту"
Когда коммитить
Правило простое:
- Функция готова и работает → коммит
- Все Hurl-тесты проходят → коммит
- Перед началом следующей функции → обязательно коммит
Без коммита — при проблеме некуда вернуться. Как 3 часа игры без сохранения.
Аналогия Git: базовые лагеря при восхождении
На Эверест не лезут за один раз. Базовый лагерь → Лагерь 1 → Лагерь 2 → … → вершина. В каждом лагере ставят палатку и накапливают запасы. При плохой погоде спускаются в предыдущий лагерь. Без лагерей в шторм — гибель.
Git-коммиты — это лагеря. При каждой готовой функции — лагерь. Если ИИ сломает следующую функцию — можно вернуться в предыдущий.
CI/CD — машина охраняет автоматически
Что такое CI/CD
CI (Continuous Integration) — автоматический запуск тестов при каждом обновлении кода. CD (Continuous Deployment) — автоматический деплой при прохождении тестов.
Сейчас достаточно знать CI. CD — потом.
Без CI:
Вы: "Добавь функцию"
ИИ: "Готово!"
Вы: (на экране проверяете только новую функцию) "Работает!"
→ Не замечаете, что существующая функция сломана
С CI:
Вы: "Добавь функцию"
ИИ: (пишет код)
Машина: (автоматически запускает все Hurl-тесты)
Машина: "Тест логина провален!"
Вы: "Логин сломан. Почини."
ИИ: (исправляет)
Машина: "Все тесты пройдены"
Вы: "Закоммить"
Вам не нужно запускать Hurl-тесты вручную каждый раз. Машина делает это автоматически.
CI как пожарная сигнализация
В здании есть пожарная сигнализация. При пожаре — автоматически срабатывает. Охранник не нужен для круглосуточного обхода.
CI — пожарная сигнализация кода. Если Hurl-тесты ломаются — автоматическое уведомление. Вам не нужно проверять вручную каждый раз.
Три инструмента вместе: храповиковая фиксация
Hurl + Git + CI дают храповик (ratchet). Храповик — шестерёнка, вращающаяся только в одну сторону. Повернул — вперёд, отпустил — стоит, но назад не идёт.
Функция 1 готова → Hurl-тест → всё проходит → коммит → фиксация
Функция 2 готова → Hurl-тест добавлен → старые + новые проходят → коммит → фиксация
Функция 3 в работе → старый Hurl-тест провален → коммит отклонён → исправление → всё проходит → коммит → фиксация
Правила просты:
- Прошедший Hurl-тест — фиксируется
- Зафиксированные тесты нельзя удалять/менять
- При новой функции — новый Hurl-тест тоже
- Все старые + все новые тесты должны пройти для коммита
Если сказать ИИ “отрефактори код”, ИИ свободно меняет код. Но если Hurl-тест провалится — коммит отклоняется. ИИ обязан сохранять всё существующее поведение.
Это точно совпадает с результатом исследования TDAD. Не процедурное указание “пиши тесты”, а конкретный контракт “этот Hurl-файл должен проходить”. Агент может выбирать метод, но не может нарушить контракт.
Как решаются проблемы урока 2
| Проблема урока 2 | Решение урока 3 |
|---|---|
| Логический дрифт | Hurl защищает существующее поведение. Поведение изменилось — провал |
| Потеря контекста | Hurl-файлы сохраняют решения навсегда. Сессия сменилась — контракт остался |
| Предвзятость лести (“всё готово”) | CI судит механически. Не самоотчёт ИИ, а pass/fail |
| Смешение решений и реализации | Hurl объявляет решения (поведение) в отдельном файле от кода |
| Умножение деградации | Храповиковая фиксация на каждом шаге сбрасывает деградацию |
Итоги
Что мы изучили:
- Hurl — объявляет контракт “должно работать так” в plain text. Проверяет не код, а поведение
- Git — создаёт точку сохранения “можно вернуться”
- CI/CD — устанавливает механическую проверку “автоматически каждый раз”
- Храповик — три вместе дают “прошёл — зафиксирован, назад не идёт”
Ключевой принцип:
Не указывайте ИИ метод. Дайте контракт — что должно проходить.
“Делай TDD” → регрессия ухудшается. “Этот Hurl должен проходить” → регрессия -70%. Разница между указанием и контрактом.
Не меняйте модель, добавьте контракт.
Анонс следующего урока
В уроке 3 мы научились защищать каждый API через Hurl. Но при росте проекта защищать нужно не только API. Структура БД, политики безопасности, UI-компоненты — всё должно быть согласовано.
В уроке 4 изучим yongol. Управление API, БД, безопасностью, UI через единую декларативную спецификацию. Перенос объекта работы ИИ с кода на спецификацию. Метод преодоления барьера 200 эндпоинтов.
Связанные статьи
- Ratchet Pattern — Почему ИИ-агент остановился на 40 из 527 функций и как механический verifier заставляет дойти до конца
- Hurl останавливает дрифт вайб-кодинга — Детальный анализ предотвращения дрифта через проверку API-контрактов с Hurl
Полный курс Reins Engineering
| Урок | Название |
|---|---|
| Урок 1 | Как командовать ИИ |
| Урок 2 | Как не доверять ИИ |
| Урок 3 | Нерушимое приложение |
| Урок 4 | Решения — за пределы кода |
| Урок 5 | ИИ на поводьях |
| Урок 6 | Прошёл — зафиксировал |
| Урок 7 | Как обратить лесть |
| Урок 8 | Фабрика агентов |
| Урок 9 | Автоматизация за пределами кода |
| Урок 10 | Закон данных |
Источники
- TDAD (Test-Driven AI Development) 2026 — процедурное указание “делай TDD” ухудшает регрессию до 9,94%, предоставление тестового файла в контексте снижает регрессию до 1,82% (-70%)
- Эксперимент Ratchet Pattern — автономный агент 40/527 (7,6%) vs храповик CLI 527/527 (100%), та же модель, разница в том, кто определяет завершение