Я снёс QA-базу данных AI-агентом. Не потому что что-то сломалось — а потому что всё работало. Тесты прошли. CI зелёный. Ревью апрувнуто. А потом QA пустое.

Что произошло
Я дебажил CI-пайплайн. Миграции не поднимались, тесты падали. Где-то в N-ном коммите насмерть упавшего CI, Cursor-агент предложил решение: добавить db:drop в таргет db-prepare Makefile'а.
# Было
db-prepare:
bundle exec rails db:create db:migrate
# Стало
db-prepare:
@echo "=== Starting db-prepare ==="
bundle exec rails db:drop db:create db:migrate --trace
Это деструктивная команда. Она удаляет всю базу. В Make-таргете, который также запускается при деплое. В этот момент система уже была обречена — но по приборам всё было чисто.
Я посмотрел diff. Апрувнул.
Потом, в следующем коммите, второй агент увидел db:drop и решил, что в проекте так принято. Добавил комментарий и пошёл дальше. Изменение нормализовалось — выглядело как осознанное решение, а не дебаг-артефакт.
Тесты прошли в фиче-ветке. CI зелёный.
Через час в слаке:
"Андрей, а ты ничего случайно не снёс нам в qa? Всю базу, например?"
Я смотрел на сообщение несколько секунд. Потом открыл Makefile. Потом понял.
db-prepare использовался не только для тестов в CI. Тот же таргет запускался при деплое на QA-окружение. Первый агент этого не знал. Я не помнил. Человеческое ревью не поймало. AI-ревью не подсветило. Все посмотрели на diff и увидели разумное изменение.
По приборам всё отлично. По факту — пустая база, нули в count.
Дальше — хуже
Следующее утро. Коллега разбирается с упавшим Elasticsearch:
"Андрей, ты решил совсем сломать db-prepare? Там теперь
rake elastic:reindex_all. CI падает на пустой базе."
Агент продолжал "чинить" Makefile. Каждый следующий агент видел то, что оставил предыдущий, и строил поверх. Никто не откатил к оригиналу.
А потом, вечером следующего дня, уже я:
"Погодите — мы же не починили db:drop. При следующем деплое на QA она опять дропнется."
Мы чуть не снесли базу дважды.
Один агент добавил деструктивную команду. Второй её нормализовал. Третий добавил сверху ещё повреждений. Каждый действовал локально, рационально, правильно — в рамках тех трёх строчек кода, которые он видел.
Код должен делать то, что написано
В нашем CI был шаг db_prepare. Он не просто запускал миграции. Он ещё и создавал базу — неявное допущение от первого деплоя. Коллега сказал: это конвенция. Я сказал: два отдельных шага, db_create и db_migrate. Если не знаешь мета-контекст, имя врёт.
Человек может догадаться, что db_prepare делает больше чем migrate. LLM доверяет тексту на 100%. Если имя говорит migrate, агент считает — migrate. Если таргет в Makefile называется db_prepare, агент считает — подготовка для тестов. Не деплой.
Каждая неявная конвенция в кодобазе — мина для AI-агента. У агента нет устной истории команды. У него есть имена файлов, имена функций и комментарии. Если они врут — хоть даже по умолчанию — агент построит на вранье.
Что на самом деле пошло не так
Простой ответ: я апрувнул плохой diff. Человеческая ошибка.
Настоящий ответ: когда я писал код руками, у меня было время подумать. Пока набираешь db:drop, в голове успевает мелькнуть: "А где ещё это используется?" Медленность создавала пространство для рефлексии. Сейчас агент выдаёт готовое решение за секунды. Я переключаюсь с написания кода на принятие кода. Из автора — в валидатора. А валидатор видит то, что ему показывают. Он не видит того, чего нет в diff'е.
AI-агенты оптимизируют локально. Они ускоряют правильный ответ на узкий вопрос. Но узкий вопрос — это почти никогда не вся проблема. Агент решил то, что видел. Я апрувнул то, что видел. Систему не видел никто.
Это не разовый случай. Это структурная проблема. Чем быстрее агент генерирует, тем меньше времени человек тратит на понимание. Чем больше агентов трогают один файл, тем больше каждый следующий строит на допущениях предыдущего. Ошибки накапливаются.
Почему мы не потеряли бизнес
Эта ошибка обошлась нам в ~30 минут. Вот почему:
QA-окружение существует. Мы не вайбкодим на прод. Есть место, где можно сломать — и это не production.
Автоматические бекапы работают. Утренний снэпшот RDS был на месте. Илья нашёл его за минуту.
Команда знает, как восстанавливать. Terraform, импорт состояния, переименование instance'ов — рутина, которую отрабатывали.
Ирония: за месяц до инцидента мы обсуждали, не убрать ли QA-окружение. "Зачем отдельное QA? Feature flags и сразу в прод, как все современные команды." Не убрали. Лень было мигрировать. Эта лень, возможно, сэкономила нам клиентские данные и репутацию.
Всё это — "скучные" практики. Бекапы, staging, runbooks, disaster recovery. То, от чего хочется избавиться, когда "мы же теперь с AI, всё быстрее".
Стандарты SDLC существуют не просто так
CI/CD, тестовые окружения, code review, disaster recovery — всё это формулировалось десятилетиями. Не потому что "так принято". А потому что люди теряли данные, деньги, клиентов, компании.
AI-агенты не отменяют эти практики. Они делают их важнее.
Раньше можно было вносить 5 изменений в день и пропускать одну ошибку из пяти. Сейчас — 50 изменений в день, и одна ошибка из пятидесяти. Но одна ошибка в день вместо одной в неделю — это радикально другой риск-профиль.
Можно ли добавить вайб-кодинг в существующие процессы? Да. Мы это делаем. Можно ли построить всё на вайб-кодинге без процессов? Нет. Вайб-кодинг — это турбонаддув. Турбонаддув на машине без тормозов — это не скорость. Это авария с ускорением.
Прежде чем доверять агентам
Вечером того дня я написал команде:
"Кароче, пацаны, всячески извините, довайбкодился."
Ответы:
"Пацаны не извиняются."
"Ниче, отработаем рестор. Мы не часто их отрабатываем."
Это здоровая инженерная культура. Не "у нас нет ошибок", а "у нас есть система, которая переживает ошибки".
AI не сломает вашу систему. Он покажет, что в ней уже было хрупким.
P.S. Если кажется, что "это же очевидно" — отлично. Значит, вы из тех, кто не потеряет прод. Но я видел достаточно команд, которые решили, что CI/CD — это легаси, а staging — лишние расходы. Им и адресую этот текст.
