Часть 20. Антипаттерны SDD
Антипаттерн — это привычка, которая выглядит как правильный процесс, но ломает результат. В SDD такие ошибки особенно коварны: файлы есть, проверки есть, агент работает быстро, но человек постепенно теряет контроль.
Эта часть нужна как диагностическая карта. Если процесс стал тяжёлым, шумным или бесполезным, начните отсюда.
Спецификация после кода
Симптом: агент сначала реализует фичу, а потом пишет requirements.md, plan.md и validation.md под уже готовый код.
Почему плохо: спецификация перестаёт направлять работу и превращается в отчёт. В таком режиме она не защищает от лишних решений агента.
Как исправить:
- перед реализацией коммитить хотя бы черновую спецификацию;
- запрещать агенту писать продуктовый код в сессии создания спецификации;
- в запросе на слияние явно показывать коммит спецификации до коммита реализации.
Гигантский requirements.md
Симптом: один файл требований содержит десятки пунктов, несколько сценариев, будущие фазы и спорные решения.
Почему плохо: агент начинает выбирать, что считать главным. Человек тоже перестаёт видеть границы.
Как исправить:
- дробить фичу на фазы;
- выносить будущие идеи в
roadmap.md; - оставлять в
requirements.mdтолько то, что нужно для текущей ветки; - спорные решения помечать как вопросы, а не как требования.
validation.md, который никто не запускал
Симптом: в проверке есть красивые факты, но нет следов их выполнения.
Почему плохо: такой файл создаёт ложное чувство готовности. Он выглядит строго, но не допускает ветку к слиянию.
Как исправить:
- рядом с каждым обязательным фактом хранить команду или ручной сценарий;
- в отчёте агента просить список пройденных, проваленных и непроверенных фактов;
- не считать факт подтверждённым, если его нельзя воспроизвести.
Ослабление фактов после ошибки
Симптом: тест упал, после чего агент меняет ожидаемый результат в validation.md, а не код.
Почему плохо: процесс начинает защищать реализацию агента, а не намерение продукта.
Как исправить:
- просить агента сначала показать расхождение без правок;
- правки
validation.mdревьюить особенно внимательно; - сохранять причину изменения факта в спецификации или запросе на слияние;
- запрещать удаление обязательных фактов без решения человека.
Ритуальный /clear
Симптом: /clear вызывается между фазами, но после него агент всё равно получает длинное объяснение из чата.
Почему плохо: команда создаёт видимость проверки переносимости. На самом деле процесс по-прежнему зависит от памяти человека.
Как исправить:
- после
/clearдавать агенту только ссылки на файлы; - проверять, может ли новая сессия понять следующую задачу из репозитория;
- если не может, дописывать спецификации, а не расширять промпт.
Навык как магическая кнопка
Симптом: команда зовёт навык Qwen Code, но никто не читает SKILL.md и не понимает, какие решения он принимает.
Почему плохо: навык становится скрытым процессом. При сбое люди не знают, что исправлять.
Как исправить:
- хранить проектные навыки в репозитории;
- ревьюить
SKILL.mdкак процессный код; - писать в навыке не только команды, но и ограничения;
- не создавать навык до 2–3 повторений ручного процесса.
QWEN.md как свалка
Симптом: в QWEN.md складывают продуктовые требования, стек, личные предпочтения, временные задачи и заметки по ошибкам.
Почему плохо: агент перестаёт отличать постоянные правила от временного контекста.
Как исправить:
- продуктовые решения хранить в
specs/;
- правила поведения агента хранить в
QWEN.md; - временные выводы переносить в память или ретроспективу;
- регулярно удалять устаревшие правила.
Хук, который молча меняет проект
Симптом: хук форматирует, переписывает или удаляет файлы без явного шага в плане.
Почему плохо: часть изменений появляется вне контроля агента и человека. Потом трудно понять, кто изменил поведение.
Как исправить:
- хуки по умолчанию должны проверять или логировать, а не менять файлы;
- автоматическое форматирование разрешать только как явное командное правило;
- все изменения файлов должны попадать в обычный
git diff; - при блокировке хук должен объяснять причину.
Память как скрытый источник истины
Симптом: агент принимает решения на основе памяти, но этих решений нет в specs/, QWEN.md или AGENTS.md.
Почему плохо: новый участник команды не увидит основание решения. Другой агент тоже может его не получить.
Как исправить:
- считать память подсказкой, а не правилом;
- переносить повторяющиеся выводы в ревьюируемые файлы;
- удалять устаревшую память;
- в споре между памятью и спецификацией выбирать спецификацию.
MCP без задачи
Симптом: к проекту подключают несколько MCP-серверов «на будущее».
Почему плохо: агент получает лишние полномочия и больше способов ошибиться. Команда перестаёт понимать, какие внешние действия вообще возможны.
Как исправить:
- подключать MCP только под конкретный сценарий;
- ограничивать список инструментов;
- хранить конфигурацию в ревьюируемом месте;
- отключать экспериментальные серверы после проверки.
Слишком большой MVP
Симптом: первая рабочая версия включает авторизацию, роли, аналитику, красивый интерфейс, миграции, импорт данных и интеграции.
Почему плохо: агент быстро создаёт много файлов, но человек не успевает понять качество решений.
Как исправить:
- первая фаза должна доказывать один риск;
- ограничивать работу временем;
- возвращаться к последнему зелёному состоянию, если ветка расползлась;
- добавлять функции только после фактов, которые уже можно проверить.
Галлюцинации в коде агента
Симптом: агент уверенно ссылается на функцию, метод или пакет, которых не существует. Импорт указывает на несуществующий модуль; вызов использует API, которое появилось только в следующей мажорной версии; в package.json добавляется зависимость, которой нет в реестре или которая называется почти как известная (например, requests-py вместо requests).
Почему плохо: галлюцинированные импорты могут не падать на этапе типов, если агент сам же дописал заглушку. Особенно опасны несуществующие имена пакетов: атакующий может заранее зарегистрировать такое имя в реестре (атака slopsquatting), и npm install тихо притянет вредоносный код.
Как исправить:
- держать список разрешённых зависимостей в
tech-stack.md; - любое добавление зависимости — отдельный шаг ревью, а не часть «реализуй фичу»;
- при первой ошибке типов или рантайма сверять версию пакета с
package.json; - перед
npm installсмотреть на имя пакета глазами; имя, отличающееся от привычного одной буквой, — стоп-сигнал; - если агент ссылается на функцию, которой раньше в коде не было, требовать ссылку: «покажи определение или скажи, где оно должно появиться».
Иллюзии тестирования
Симптом: npm test зелёный, но баг остаётся. Тесты есть, но они не проверяют то, что заявлено.
Типичные подвиды:
- тавтологический тест: тест сравнивает результат функции с тем же выражением, что и в функции, — переименование переменной всё сломает, но логика никогда не проверяется;
- тест-зеркало: тест проверяет, что функция возвращает то, что вернула, без независимого ожидаемого значения;
- обман через снапшот: первый запуск создаёт снапшот, второй сравнивает с ним же; ошибка фиксируется в снапшоте и считается «правильной»;
- тест, который не падает ни при какой ошибке: единственное утверждение — что функция не выбросила исключение.
Почему плохо: зелёный набор тестов перестаёт быть фактом готовности. Спецификация формально выполнена («покрытие 90%»), но никаких реальных гарантий нет.
Как исправить:
- в
validation.mdтребовать факт-репро: команду, которая до фикса падает, а после — проходит (особенно для багфиксов, см. часть 11); - при ревью читать сами тесты, а не только цифру покрытия;
- для критичных мест применять мутационное тестирование (для Vitest есть Stryker): сервис вносит мелкие правки в код и проверяет, замечают ли их тесты. Если ни одна мутация не ловится, тесты ничего не проверяют;
- запрещать снапшоты для бизнес-логики; снапшоты допустимы только там, где результат — человекочитаемый рендер.
Разработчик не понимает свой PR
Симптом: автор открывает запрос на слияние, но не может объяснить, почему конкретное решение принято; в ответ на вопрос ревьюера он повторно спрашивает агента и пересылает ответ.
Почему плохо: ответственность за код размывается. Через полгода никто в команде не сможет сказать, почему здесь именно такая обработка ошибок и был ли это сознательный выбор. Если автор не понимает свой PR, ревьюер не может опереться на его суждение, а будущий читатель будет блуждать в гипотезах.
Как исправить:
- ввести правило: автор PR обязан в описании одним абзацем своими словами объяснить, что и зачем сделано (см. шаблон в приложении C);
- ревьюер задаёт хотя бы один вопрос, на который ответ есть только у человека («почему здесь чтение из базы вне транзакции?»); если автор не отвечает или отвечает выдержкой из чата, PR возвращается на доработку;
- в команде — поощрять паттерн «парный SDD»: один пишет спецификацию, второй ревьюит её до реализации (часть 22, парный зачёт);
- для себя — после слияния перечитывать
git diffи формулировать вслух: «я сделал X, потому что Y». Если объяснить не получается, в следующей фиче запрашивайте у агента не только код, но и пояснение в комментариях к PR.
Диагностический чек-лист
Если SDD перестал помогать, ответьте:
- Есть ли фичи, где спецификация написана после кода?
- Можно ли выполнить факты из
validation.mdбез истории чата? - Понятно ли, какие правила живут в
QWEN.md, а какие вspecs/? - Есть ли хуки, которые меняют файлы без явного шага?
- Есть ли MCP-серверы без текущей задачи?
- Есть ли решения, которые живут только в памяти агента?
- Может ли новый агент после
/clearпродолжить работу по файлам? - Можно ли объяснить текущую фазу проекта за одну минуту?
Если на три вопроса ответ отрицательный, не добавляйте новые инструменты. Упростите процесс.
Связанные части
- Часть 16 — те же ошибки с позиции ревьюера: как поймать антипаттерн в чужом pull-запросе.
- Часть 18 — антипаттерны, которые одновременно являются угрозами безопасности (секреты в спецификациях, MCP без ревью, ослабление
validation.md). - Часть 9 — матрица «тип фичи → уровень фактов», которая прямо лечит антипаттерн «слабый
validation.md».