Claude Code для сбоев CI: попросите его процитировать ошибочный вывод, предложить минимальное исправление и добавить регрессионный тест, чтобы предотвратить повторение.

Сбой CI обычно не таит мистику. Лог показывает, где всё остановилось, какая команда завершилась с ошибкой и само сообщение об ошибке. Хороший лог содержит трассировку стека, ошибку компиляции с файлом и номером строки или отчёт теста с указанием, какое утверждение упало. Иногда есть подсказка в стиле diff — например, "expected X, got Y" — или явный провал шага вроде "lint", "build" или "migrate database".
Проблема в том, что люди (и ИИ) часто воспринимают лог как фоновый шум. Если вставить длинный лог и попросить "исправление", многие модели прыгают к знакомому объяснению вместо чтения последних значимых строк. Догадки усугубляются, когда ошибка выглядит распространённой ("module not found", "timeout", "permission denied"). В результате вы получаете большой рефактор, новую зависимость или совет "попробуйте обновить всё", который не соответствует реальной причине.
Цель не в том, чтобы "как‑нибудь заставить пройти". Всё проще:
На практике «минимальное исправление» обычно одно из этого: пара строк кода в одном месте, отсутствующий импорт или неправильный путь, значение конфигурации, явно неверное для CI‑окружения, или откат случайно введённого ломательного изменения вместо переработки дизайна.
Последующий тест тоже важен. Один удачный прогон CI не равен защите от повторений. Если сбой возник из-за краевого случая (null‑вход, таймзона, округление, права), добавьте регрессионный тест, который падал до фикса и проходит после. Так единичная спасательная правка превращается в страховочный барьер.
Большинство плохих фиксов начинаются с отсутствия контекста. Если вы вставляете только последнюю красную строку, модель вынуждена гадать, что было раньше, а догадки часто приводят к переписыванию.
Старайтесь дать достаточно деталей, чтобы кто‑то мог проследить сбой от первой реальной ошибки до конца, а затем изменить как можно меньше.
Скопируйте это в своё сообщение (дословно, когда можете):
go test ./..., npm test, flutter test, golangci-lint run).Добавьте ограничения простыми словами. Если хотите минимальный фикс, скажите это: никаких рефакторов, никаких изменений поведения без необходимости, патч ограничен зоной провала.
Простой пример: CI падает на шаге линтинга после обновления зависимости. Вставьте вывод линтера начиная с первого предупреждения, включите команду CI и укажите изменение версии пакета. Этого обычно достаточно, чтобы предложить однострочное изменение конфигурации или небольшую правку кода, а не переформатирование половины репозитория.
Если нужен вариант, который можно прямо вставить, эта структура обычно достаточна:
CI command:
Failing output (full):
Recent changes:
Constraints (smallest fix, no refactor):
Flaky? (runs attached):
Когда модель промахивается на сбое CI, обычно причина в том, что подсказка позволяет ей гадать. Ваша задача — заставить модель показать ход мысли, опираясь на точный вывод лога, а затем придерживаться минимального изменения, которое может сделать задачу зелёной.
Потребуйте доказательства и краткий план. Хорошая подсказка навязывает пять вещей:
Неопределённость допустима. Скрытая неопределённость — то, что тратит время.
Вставьте это в начало вопроса про CI:
Use ONLY the evidence in the CI output below.
1) Quote the exact failing lines you are using.
2) Give ONE sentence: the most likely cause.
3) Propose the smallest fix: 1-3 edits, with file paths.
4) Do NOT do formatting/renames/refactors or "cleanup".
5) List uncertainties + the one extra detail that would confirm the diagnosis.
Если лог показывает "expected 200, got 500" и трассировку в user_service.go:142, эта структура подтолкнёт ответ в сторону той функции и маленького охранного условия или обработки ошибки, а не редизайна эндпойнта.
Самые быстрые победы приходят от подсказки, которая заставляет цитировать логи, держит ограничения и останавливается, если чего‑то не хватает.
You are helping me fix a CI failure.
Repo context (short):
- Language/framework:
- Test/build command that failed: <PASTE THE EXACT COMMAND>
- CI environment (OS, Node/Go/Python versions, etc.):
Failing output (verbatim, include the first error and 20 lines above it):
<PASTE LOG>
Constraints:
- Propose the smallest possible code change that makes CI pass.
- Do NOT rewrite/refactor unrelated code.
- Do NOT touch files you do not need for the fix.
- If behavior changes, make it explicit and justify why it is correct.
Stop rule (no guessing):
- If the log is incomplete or you need more info (missing stack trace, config, versions, failing test name), STOP and ask only the minimum questions needed.
Your response format (follow exactly):
1) Evidence: Quote the exact log lines that matter.
2) Hypothesis: Explain the most likely cause in 2-4 sentences.
3) Smallest fix: Describe the minimal change and why it addresses the evidence.
4) Patch: Provide a unified diff.
5) Follow-up: Tell me the exact command(s) to rerun locally to confirm.
Then, write ONE regression test (or tweak an existing one) that would fail before this fix and pass after it, to prevent the same failure class.
- Keep the test focused. No broad test suites.
- If a test is not feasible, explain why and propose the next-best guardrail (lint rule, type check, assertion).
Две детали, которые сокращают количество итераций:
Самый быстрый способ потерять час — согласиться на «очистку», которая меняет несколько вещей сразу. Определите "минимальное" заранее: самый маленький дифф, который заставляет упавшую задачу пройти, с наименьшим риском и быстрой верификацией.
Простое правило работает: сначала исправьте симптом, потом решите, стоит ли рефакторить. Если лог указывает на один файл, одну функцию, один отсутствующий импорт или один краевой случай, двигайтесь туда. Избегайте правок "пока тут".
Если вам нужны варианты, попросите два и только два: "наиболее безопасное минимальное исправление" против "самого быстрого минимального исправления". Вы хотите компромиссы, а не меню.
Также требуйте локальной верификации, совпадающей с CI. Попросите ту же команду, что выполняет пайплайн (или ближайший эквивалент), чтобы подтвердить за минуты:
# run the same unit test target CI runs
make test
# or the exact script used in CI
npm test
Если ответ предлагает крупное изменение, возьмите паузу и спросите: «Покажи самый маленький патч, который исправляет падающее утверждение, без сторонних форматирований и переименований.»
Исправление без теста — это ставка на то, что проблема не вернётся. Всегда требуйте один последующий регрессионный тест, который падает до правки и проходит после.
Будьте конкретны в том, что значит «хорошо»:
Полезный шаблон требует четырёх вещей: куда положить тест, как его назвать, какое поведение покрывает и короткое объяснение, почему он предотвращает регрессию.
Короткий добавочный список:
Пример: CI показывает panic, когда обработчик API получает пустой ID. Не просите «тест для этой строки». Попросите тест на некорректные ID (пустая строка, пробелы, неправильный формат). Минимальное исправление может быть охранным условием, возвращающим 400. Последующий тест должен проверять несколько невалидных входов, чтобы следующий рефакторинг, который уберёт проверку, немедленно ломал CI.
Если в проекте уже есть соглашения по тестам, укажите их. Если нет — попросите следовать соседним тестам в той же папке и сделать новый тест минимальным и читабельным.
Вставьте участок лога с ошибкой и 20–40 строк выше, а также точную команду, которую запускал CI, и ключевые данные окружения (ОС, версии рантайма, важные флаги).
Попросите рестейтнуть, что упало простыми словами и указать строки вывода, которые это подтверждают. Если модель не может процитировать лог — значит, она его не прочитала.
Попросите самое маленькое изменение, которое заставит упавшую команду пройти. Отбейте любые рефакторы. Прежде чем применять, получите список:
Примените патч и заново запустите ту же упавшую команду локально. Если всё ещё падает — вставьте только новый упавший вывод и повторите. Маленький контекст даёт сфокусированный ответ.
Когда зелёный, добавьте один последующий тест, который падал до патча и проходит после. Сфокусируйте тест: один тест, одна причина.
Перезапустите команду с новым тестом, чтобы подтвердить, что вы не просто заглушили проблему.
Попросите короткое сообщение коммита и описание PR: что падало, что изменилось, как вы проверили, и какой тест предотвращает повтор. Ревьюерам проще принимать изменения, когда мотивация ясна.
Распространённый случай: всё работало локально, но небольшое изменение ломает тесты в CI. Вот простой пример из Go API, где хендлер стал принимать значение только с датой (2026-01-09), а код всё ещё парсил только полные RFC3339‑таймстемпы.
Это тот фрагмент лога, который стоит вставить (коротко, но с ошибкой):
--- FAIL: TestCreateInvoice_DueDate (0.01s)
invoice_test.go:48: expected 201, got 400
invoice_test.go:49: response: {\"error\":\"invalid due_date: parsing time \\\"2026-01-09\\\" as \\\"2006-01-02T15:04:05Z07:00\\\": cannot parse \\\"\\\" as \\\"T\\\"\"}
FAIL
exit status 1
FAIL\tapp/api\t0.243s
Далее используйте подсказку, которая заставляет опираться на доказательства, предложить минимальный фикс и тест:
You are fixing a CI failure. You MUST use the log to justify every claim.
Context:
- Language: Go
- Failing test: TestCreateInvoice_DueDate
- Log snippet:
<PASTE LOG>
Task:
1) Quote the exact failing line(s) from the log and explain the root cause in 1-2 sentences.
2) Propose the smallest possible code change (one function, one file) to accept both RFC3339 and YYYY-MM-DD.
3) Show the exact patch.
4) Add one regression test that fails before the fix and passes after.
Return your answer with headings: Evidence, Minimal Fix, Patch, Regression Test.
Хороший ответ укажет на несоответствие форматов парсинга и предложит небольшое изменение в одной функции (например, parseDueDate в invoice.go): сначала пробовать RFC3339, а затем fallback к 2006-01-02. Никаких рефакторов и новых пакетов.
Регрессионный тест — страховка: отправить due_date: "2026-01-09" и ожидать 201. Если кто‑то позже уберёт fallback, CI снова сломается тем же классом проблем.
Самый быстрый способ потерять час — давать обрезанный вид проблемы. Логи CI шумные, но полезная часть часто лежит в 20 строках над финальной ошибкой.
Одна ловушка — вставлять только последнюю красную строку (например, "exit 1") и скрывать настоящую причину раньше (отсутствующая переменная окружения, падение снапшота, первый тест, который рухнул). Решение: вставлять команду CI и окно лога, где появляется первая реальная ошибка.
Другой источник потерь — позволить модели «прихорашивать» код по дороге. Форматирование, обновления зависимостей или рефакторы сложнее ревьюить и легче ломают что‑то ещё. Решение: зафиксируйте зону правки как минимальную.
Паттерны, за которыми стоит следить:
Если подозреваете флакичность, не маскируйте её ретраями. Уберите случайности (фиксированное время, seed для RNG, изолированные папки), чтобы сигнал был чистым.
Прежде чем пушить, сделайте короткую проверку. Цель — убедиться, что изменение минимально, воспроизводимо и реально исправляет проблему.
Наконец, запустите чуть более широкий набор целей, чем только упавшая job (например, линт + юнит‑тесты). Частая ошибка — фикс, который делает оригинальную задачу зелёной, но ломает другой таргет.
Если хотите экономить время регулярно, относитесь к подсказке и формату ответа как к командному процессу. Цель — повторяемые входные данные, повторяемые выходы и меньше "таинственных фиксов".
Сделайте вашу лучшую подсказку общим сниппетом:
(1) доказательства, (2) однострочный диагноз, (3) минимальное изменение, (4) последующий тест, (5) как проверить локально. Когда все пользуются одинаковым форматом, ревью идут быстрее — ревьюер знает, где смотреть.
Лёгкий цикл привычки для команд:
Если предпочитаете чат‑первый рабочий процесс для быстрой итерации, вы можете выполнять тот же цикл «фикс→тест» внутри Koder.ai, использовать снимки при экспериментах и экспортировать изменения, когда будете готовы смёржить в основной репозиторий.
Начинайте с первого реального сообщения об ошибке, а не с финального exit 1.
Попросите модель доказать, что она прочитала лог.
Используйте ограничение вроде:
Обычно это минимальный патч, который заставляет упавший шаг пройти.
Чаще всего это:
Избегайте «очистки» и рефакторов до тех пор, пока CI не станет зелёным.
Вставьте достаточно контекста, чтобы воспроизвести сбой, а не только последнюю красную строку.
Включите:
Да — чётко пропишите ограничения простым языком и повторите их.
Примеры:
Это заставляет ответ быть фокусным и обозримым при ревью.
Сначала исправляйте самую раннюю реальную ошибку.
Если сомневаетесь, попросите модель указать первый упавший шаг в логе и действуйте по нему.
Рассматривайте флакичность как сигнал к устранению случайности, а не как повод добавлять ретраи.
Типичные стабилизаторы:
После детерминизации минимальное исправление обычно очевидно.
Запустите ту же команду, что и CI, локально.
Если локально воспроизвести трудно, попросите минимальное repro внутри репозитория (один тест/таргет), который даёт ту же ошибку.
Напишите один сфокусированный регрессионный тест, который падает до исправления и проходит после.
Хорошие цели:
Если это ошибка линтера/сборки, эквивалентом теста может быть ужесточённое правило линта или чек, предотвращающий ту же ошибку.
Используйте снимки и откаты, чтобы эксперименты были обратимыми.
Практичный цикл:
Снимки помогают не смешивать экспериментальные правки с финальным патчем для мержа.
go test ./...npm testflutter test