JavaRush /Курсы /Claude code /IDE, терминал и логи как доказательства

IDE, терминал и логи как доказательства

Claude code
8 уровень , 1 лекция
Открыта

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-а, чтобы обратно вернулась уже короткая проверяемая выжимка.

1
Задача
Claude code, 8 уровень, 1 лекция
Недоступна
Снятие короткого failure snippet через терминал
Снятие короткого failure snippet через терминал
1
Задача
Claude code, 8 уровень, 1 лекция
Недоступна
Focused investigation через selection-as-context и trimmed log
Focused investigation через selection-as-context и trimmed log
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ