1. Одних файлов уже мало
Код — главный источник истины. Но между «в коде написано» и «в рантайме произошло» лежит пропасть.
В лекции про API_MAP.md вы искали эндпоинты, контроллеры, клиентов, очереди, конфиги и тесты. Это статическая карта проекта. Возьмём Commerce OS: вы нашли POST /api/orders, увидели OrderController, поняли, какой сервис создаёт заказ, нашли тесты. А интеграционный тест говорит: при пустом email система должна вернуть 400, но возвращает 500. Карта из файлов — это схема, а не поведение.
Держите в голове различие:
| Источник | На какой вопрос отвечает |
|---|---|
| Код и конфиги | «Где это должно работать и как это задумано?» |
| Вывод терминала и упавшие тесты | «Что реально сломалось прямо сейчас?» |
| Stack trace и логи рантайма | «Где именно это упало или пошло не туда?» |
| Скриншот интерфейса | «Что в этот момент увидел пользователь?» |
Код показывает, как устроен механизм. Сигналы выполнения показывают, как он повёл себя под конкретным вводом, командой и сессией. Эти сигналы и нужны Claude Code: они сужают пространство догадок. Вы не просите «угадай, где баг» — вы приносите улики.
Пока вы не увидели команду, которая воспроизводит сбой, и вывод упавшего теста, вы в зоне предположений. А предположения принимаются только после проверки.
2. IDE — точный канал контекста, а не редактор покрасивее
В работе с Claude Code IDE ценна не красотой, а точностью. Она даёт модели именно тот фрагмент, который важен сейчас: конкретный метод, блок условий, строку в контроллере. Это контекст через выделение — selection-as-context.
Расследуете баг в Commerce OS: при пустом email checkout должен вернуть 400, а приходит 500. Типичная ошибка — отправить «проверь, почему заказ ломается» и разрешить читать весь модуль orders. Это уже не расследование, а экскурсия по району. Точнее — открыть OrderController, выделить метод и сказать: «используйте выделенный код как основной контекст».
@PostMapping("/api/orders")
public ResponseEntity<?> createOrder(@RequestBody CreateOrderRequest request) {
orderValidator.validate(request); // при невалидных данных ждём 400
Order order = orderService.create(request); // сейчас где-то здесь уходим в 500
return ResponseEntity.ok(order);
}
Фрагмент работает в связке с точным запросом:
Используйте выделенный метод как основной контекст.
Вот цель: понять, почему при пустом email endpoint возвращает 500 вместо 400.
Ссылайтесь на конкретные строки и не делайте предположений без evidence.
Запрос хорош не формулировкой, а тем, что он узкий: ограничена область поиска, обозначено ожидаемое поведение, задана работа от фактов. Claude легче с 12 строками, чем с 600.
Вторая сильная сторона IDE — привязка к file:line. Пишете не «смотри OrderController», а OrderController.java:42-46 — и модель не уходит обсуждать соседние методы и архитектуру модуля «на всякий случай». А «на всякий случай» — дорогой способ загрязнить контекст.
3. Терминал: показывайте ошибку, а не пересказывайте
Баг воспроизводится — не объясняйте его словами, покажите как факт. Вывод терминала для этого почти идеален: там команда, результат, иногда путь к файлу и намёк на причину.
Вместо «заказ почему-то падает» дайте команду и результат:
./gradlew test --tests OrderControllerTest
# FAILED: expected: <400> but was: <500>
# at OrderControllerTest.createOrder_validationFails(OrderControllerTest.java:73)
С такой уликой разговор другой:
Вот команда, которая воспроизводит проблему:
./gradlew test --tests OrderControllerTest
Вот результат:
FAILED: expected: <400> but was: <500>
at OrderControllerTest.createOrder_validationFails(OrderControllerTest.java:73)
Используйте это как evidence. Найдите минимальную причину расхождения.
Полезен не только вывод, но и команда, которая его породила. Без команды модели сложнее восстановить контекст: это unit-тест? integration? локальный запуск? build? smoke check? Один и тот же текст ошибки в разных командах значит разное.
И вспомните модуль про контекст. Скопировать в чат весь лог на 5000 строк — формально evidence есть, практически вы превратили сессию в свалку. Вырежьте релевантный кусок: обычно хватает 10–30 строк вокруг ошибки. Часть вывода опустили — нормально, просто пометьте, что лог сокращён.
И из безопасного старта: перед передачей terminal output проверьте, нет ли там секретов, токенов, внутренних URL и других чувствительных данных. AI не «забывает по-человечески» — приносите вычищенный материал.
4. Stack trace — это маршрут до строки
Stack trace выглядит как проклятие: длинный текст, куча классов, framework internals, пол-экрана скобок. Но это одна из самых коротких дорог от симптома к месту поломки.
Весь trace разбирать не нужно. Смотрите на тип ошибки, потом ищите первые строки своего проекта, а не внутренности Spring, JUnit или другого фреймворка:
java.lang.NullPointerException: Cannot invoke "String.trim()" because "customerEmail" is null
at src/orders/OrderService.create(OrderService.java:51)
at src/orders/OrderController.createOrder(OrderController.java:45)
at OrderControllerTest.createOrder_validationFails(OrderControllerTest.java:73)
Это уже карта движения: тест вызвал контроллер, контроллер — сервис, сервис упал на строке 51, потому что customerEmail оказался null, а код сделал trim(). Модель не гадает про «что-то с валидацией на фронтенде» — она видит реальный путь выполнения.
Откройте проблемный метод в IDE — получите связку runtime trace + точечный фрагмент:
public Order create(CreateOrderRequest request) {
String email = request.customerEmail().trim(); // здесь и падаем при null
paymentPolicy.check(request);
return orderRepository.save(new Order(email));
}
Только код — можете не заметить проблему. Только trace — знаете место падения, но не видите соседний контекст. Вместе — почти завершённая инженерная гипотеза.
Логи рантайма работают так же, даже без полного stack trace. Видно в логах email=null, а сразу после — creating order: это уже звено доказательной цепочки. Главное — показывать релевантный фрагмент, а не пересказывать словами.
5. Скриншот — тоже evidence, если есть подпись
Две крайности: одни не используют скриншоты как «нетехническое», другие прикладывают картинку как реликвию и ждут, что она всё объяснит сама. Скриншот полезен, когда проблема в состоянии интерфейса: пустой экран, неверная ошибка, пропавшая кнопка, наложение элементов, сломанная модалка.
Тот же checkout в Commerce OS: пользователь вводит пустой email, жмёт «Оформить заказ» и вместо ошибки валидации получает пустую страницу. «Фронт разваливается» — мало. Скриншот с короткой подписью — яснее:
Скриншот: checkout-empty-email.png
Подпись: после клика по «Оформить заказ» страница не показывает ошибку валидации, а уходит в пустой экран.
Картинка не заменяет логи, тесты и trace. Но она отвечает на вопрос: что увидел пользователь в момент проблемы. Это важно там, где backend и frontend расходятся: backend честно вернул 500, а frontend просто очистил экран. Для расследования это две разные проблемы — скриншот не даёт их смешать.
Правило простое: у скриншота почти всегда подпись в одну-две строки. Без подписи Claude интерпретирует изображение сам — снова догадки. С подписью картинка становится уликой.
6. Собираем маленький пакет улик для Claude Code
Для большинства задач не нужен гигантский отчёт. Достаточно короткого, аккуратно собранного пакета: ровно столько, чтобы Claude Code понял проблему и не утонул в шуме.
Цель:
Понять, почему POST /api/orders при пустом email возвращает 500 вместо 400.
Контекст:
Используйте выделенный метод OrderController.createOrder как основной контекст.
Команда воспроизведения:
./gradlew test --tests OrderControllerTest
Результат:
FAILED: expected: <400> but was: <500>
at OrderControllerTest.createOrder_validationFails(OrderControllerTest.java:73)
Stack trace (сокращён):
java.lang.NullPointerException: Cannot invoke "String.trim()" because "customerEmail" is null
at src/orders/OrderService.create(OrderService.java:51)
Скриншот:
checkout-empty-email.png — после клика страница уходит в пустой экран.
Что нужно от Claude:
Найти минимальную причину, сослаться на строки кода и предложить наименьшее исправление без broad refactor.
Обратите внимание, как здесь сочетаются все уже знакомые нам практики. Есть цель из task spec. Есть узкий контекст через выделение в IDE. Есть команда и её вывод. Есть сокращённый stack trace. Есть визуальное подтверждение со стороны интерфейса. И есть явная просьба не расползаться в большой рефакторинг. Такой пакет хорошо работает не только в текущей сессии, но и тогда, когда вы возвращаетесь к задаче после паузы и не хотите заново рассказывать всю историю.
Эта же привычка очень полезна и для ваших артефактов вроде API_MAP.md. Если раньше запись про POST /api/orders опиралась только на контроллер и сервис, то после расследования вы уже можете привязать к ней и доказательства из рантайма: какой тест подтверждает поведение, какая команда воспроизводит сбой, какие ограничения нашлись валидацией. Карта проекта от этого становится живее и честнее.
В какой-то момент вы заметите интересный перелом. До него вы просите Claude Code «подумать, что тут не так». После него вы приносите ему конкретные улики и просите провести расследование. И вот в этой точке Claude перестаёт быть гадалкой с клавиатурой и начинает работать как настоящий инженерный помощник.
Такой пакет улик нужен не только для исправления бага. Им также удобно уточнять спорную запись в API_MAP.md, собирать troubleshooting note или черновик документации и, если расследование разрастается, выносить широкое чтение в отдельное окно вроде subagent-а, чтобы обратно вернулась уже короткая проверяемая выжимка.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ