JavaRush /Курси /Claude code /Дослідження в режимі планування для issue

Дослідження в режимі планування для issue

Claude code
Рівень 17 , Лекція 2
Відкрита

1. Розслідування відбувається раніше за правку

Дуже хочеться після читання тікета й кількох файлів сказати Claude: «Ну все зрозуміло, виправляй». А це ж найдорожча фраза в усьому відлагодженні. Після неї разом із багом «випадково покращується» архітектура, змінюється API, ламається сусідній сценарій, народжується нова ексклюзивна проблема. Тому розслідування я тримаю нудним і дисциплінованим.

Intake вже зробив важливу частину роботи: відокремив symptom, user impact, assumptions і open questions. Але поки що це карта людською мовою. Давайте пройдемося по коду й перетворимо assumptions на evidence — не переходячи до редагування.

Спочатку зрозуміти, потім змінювати.

У різних версіях Claude Code точна назва команди або режиму може відрізнятися, тому орієнтуйтеся на поточний /help. Але суть режиму планування завжди одна: Claude читає, шукає, пояснює, збирає evidence і не редагує файли. Нуль правок. Нуль «ну я тут заодно вже виправив».

Ось як виглядає цей перехід у вигляді простої схеми:

flowchart LR
    A[Issue Intake Note] --> B[Режим планування]
    B --> C[Релевантні файли]
    B --> D[Точки входу та тести]
    B --> E[Ризики та unknowns]
    C --> F[Investigation Note]
    D --> F
    E --> F

Зверніть увагу на важливу думку: після хорошого розслідування код усе ще не змінений. Для новачка це іноді виглядає дивно: «Я попрацював, а баг на місці». Насправді це сильний стан: карта місцевості є, а ви ще нічого не зіпсували.

2. Результат розслідування: Investigation Note

Щоб розслідування не перетворилося на нескінченну розмову з Claude про життя, архітектуру й погоду в логах, заздалегідь вирішіть, що хочете отримати на виході. Не гарний текст, а робочий артефакт — Investigation Note: короткий щільний звіт, де живе проблема і що ми про неї вже знаємо на рівні коду.

Для поточного issue цього достатньо представити у вигляді таблиці:

Що потрібно з’ясувати Приклад для Commerce OS Навіщо це знати
Точка входу Де обробляється POST /api/orders Щоб розуміти, як запит потрапляє в backend
Бізнес-логіка Де обчислюється сума замовлення Щоб знайти мінімальну точку зміни
Наявні тести Чи є тест на порожній кошик Щоб не писати все з нуля й не дублювати покриття
Обробка помилок Чи вже є спільний мапінг 400 Щоб не вигадувати новий механізм там, де старий уже є
Ризики та unknowns Що очікує frontend, де ще використовується метод Щоб не вийти за scope і не зламати сусідні сценарії

Гарний запит до Claude в режимі планування може виглядати так:

Перейди в режим планування. Не редагуй файли.
Досліди, де реалізована помилка з issue #482.
Поверни:
1. релевантні файли,
2. ключові методи та точки входу,
3. наявні тести,
4. ймовірні точки зміни,
5. ризики,
6. assumptions і evidence під кожен висновок.

Зверніть увагу: тут немає прохання «запропонуй гарний рефакторинг» і «одразу виправ». Спочатку — карта проблеми. І ще одна тонкість: це не широке знайомство з codebase, ми звужуємося до одного issue.

3. Не починайте з порожнього екрана

Щоб не говорити абстрактно, візьму навчальний приклад із Commerce OS. Intake готовий, фрагмент артефакту:

## Проблема
POST /api/orders повертає 500 за порожнього items[].

## Вплив на користувача
Користувач отримує загальну помилку замість зрозумілої валідації.

## Відомі докази
- stack trace із тікета
- відтворення: POST /api/orders із порожнім items[]

## Відкриті питання
- чи потрібен окремий код помилки EMPTY_CART?
- чи має frontend показувати спеціальний текст?

## Поза межами
- редизайн кошика
- зміни checkout UX

Тепер до справи. Найкорисніша звичка тут — не починати розслідування з порожнього екрана. У вас уже є CODEBASE_INVENTORY.md з модуля про аналіз проєкту та API_MAP.md з модуля про карту API — стартові орієнтири. Якщо в API_MAP.md є запис про /api/orders, не вдавайте, ніби вперше бачите цей endpoint. Використовуйте зібрану карту, а не будуйте заново героїчним зусиллям.

Якщо issue надходить через issue-tracker з Workflow Kit — ще краще: попросіть Claude підтягнути текст тікета, релевантні коментарі та labels, не копіюючи руками. Наприклад, коментар frontend-розробника про очікуваний код помилки нерідко корисніший за половину обговорення. Але й тут потрібна дисципліна: беремо те, що допомагає розслідуванню, а не весь корпоративний роман у чотирьох томах.

4. Від тікета до файлів: точки входу та зв’язки

А тепер спускаємося з небес на землю — до найприкладнішої частини. Розслідування майже завжди йде однією й тією самою траєкторією: точка входу → бізнес-логіка → тести → обробка помилок → change points. Якщо ви тільки починаєте програмувати, вважайте це надійним маршрутом. Нудно, але працює краще, ніж «я інтуїтивно відчуваю, що баг живе в сервісах».

Якщо rg звучить як назва бойового дроїда з наукової фантастики — не лякайтеся. Це просто швидкий пошук по проєкту. У терміналі можна почати так:

rg '@PostMapping\("/api/orders"' src test     # шукаємо контролер маршруту
rg 'calculateTotal\(' src test                # шукаємо обчислення суми та його тести
rg 'IllegalArgumentException|ControllerAdvice' src test  # шукаємо загальну обробку помилок

Навіть якщо ви не любите термінал, той самий маршрут проходиться через пошук в IDE. Важливо не те, яким саме інструментом ви шукаєте, а в якому порядку ви це робите. Спочатку вхід, потім логіка, потім перевірки.

Припустімо, розслідування виводить нас на контролер створення замовлення:

@PostMapping("/api/orders")
public OrderResponse create(@RequestBody CreateOrderRequest request) {
    BigDecimal total = orderService.calculateTotal(request.items()); // тут можлива помилка
    return orderFacade.createOrder(request, total);
}

Це вже evidence, а не здогадка. Ми бачимо, що запит справді входить через цей метод, і далі йде в orderService.calculateTotal(...). Наступна зупинка — сервіс:

public BigDecimal calculateTotal(List<OrderItem> items) {
    Currency currency = items.get(0).currency(); // порожній список ламає обчислення
    BigDecimal total = BigDecimal.ZERO;
    for (OrderItem item : items) {
        total = total.add(item.priceIn(currency));
    }
    return total;
}

Тепер у нас з’являється сильна гіпотеза: падіння на порожньому списку відбувається саме тут. Але поки це ще не фінальна істина, а добре обґрунтована гіпотеза. Чому? Тому що нам ще потрібно перевірити, чи немає поруч загальної валідації, уже наявного обробника помилок і чи не використовується цей метод десь ще, окрім створення замовлення.

І ось тут розслідування стає інженерним, а не «магічним». Ми не кажемо: «Ага, зрозумів, ось root cause». Ми кажемо: «Є кодовий фрагмент, який підтверджує ймовірну точку падіння. Тепер перевіримо сусідні умови». Це доросла різниця.

5. Відрізняємо evidence від гіпотези

Одна з найкорисніших звичок, яку ви можете винести з цієї лекції, звучить просто: кожен висновок повинен мати статус. Або це evidence, або hypothesis, або assumption, або unknown. Якщо все змішати в одну купу, Investigation Note перетвориться на впевнений текст, який дуже погано витримує зустріч із реальним diff.

Ось проста таблиця для нашого випадку:

Формулювання Статус Чому
POST /api/orders обробляється в OrderController#create Evidence Ми бачимо анотацію маршруту та метод
calculateTotal() падає на порожньому списку Evidence У коді є items.get(0) без перевірки
Це єдина причина бага Hypothesis Потрібно ще перевірити валідацію та обробку винятків
Frontend чекає код EMPTY_CART Assumption Це може йти з коментаря, але не з коду backend
calculateTotal() більше ніде не використовується Unknown, поки не перевірили Потрібен пошук usages

Дуже часта помилка новачка виглядає так: побачили підозрілий рядок — оголосили справу розкритою. Але гарне investigation живе трохи інакше. Воно постійно ставить уточнювальні запитання. Чи є вже @ControllerAdvice, який уміє перетворювати IllegalArgumentException на 400? Чи є тести на схожі сценарії валідації? Чи не використовується calculateTotal() у пакетній обробці замовлень, де порожній список взагалі не має доходити до сервісу?

Іноді Claude вже на цьому етапі корисно попросити не «пояснити архітектуру», а відповісти дуже приземлено: що є фактом, а що припущенням. Такий запит звучить майже смішно, але працює чудово:

Для кожного висновку в розслідуванні познач статус:
evidence, hypothesis, assumption або unknown.
Не перетворюй hypothesis на факт.

Тут ми буквально вчимо AI не піддаватися його улюбленій слабкості: впевнено звучати там, де треба чесно сказати «поки не знаю». І, чесно кажучи, людям це теж іноді корисно.

6. Оформлюємо Investigation Note для інших

Хороше розслідування цінне не лише тим, що ви самі щось зрозуміли. Воно має залишати після себе артефакт, який зможе за дві хвилини прочитати інший інженер, ревʼюер або ви самі через три дні. І ось тут довга історія чату майже завжди програє короткій Investigation Note.

Приклад для нашого issue може виглядати так:

# Примітка розслідування

## Релевантні файли
- orders/api/OrderController.java
- orders/service/OrderService.java
- orders/api/GlobalExceptionHandler.java
- orders/test/OrderControllerWebTest.java

## Ймовірні точки зміни
- валідація empty items до calculateTotal()
- повернення 400 замість 500
- можливо: reuse наявного error mapping

## Докази
- route знайдено в OrderController#create
- stack trace вказує на OrderService.calculateTotal:42
- у calculateTotal є items.get(0) без перевірки
- тесту на empty cart в OrderControllerWebTest не знайдено

## Невідоме
- чи є інші usages calculateTotal()
- який error code очікує frontend

Зверніть увагу на стиль цього документа. Він короткий. У ньому немає роману про архітектурну велич системи. Кожна секція відповідає на конкретне запитання. Такий артефакт набагато корисніший, ніж 40 повідомлень у сесії, де вдалі думки перемішані з невдалими гіпотезами й запитаннями на кшталт «а може, все-таки переписати сервіс?». Ні, не треба. Ми сьогодні не переписуємо сервіс. Ми сьогодні акуратно розуміємо, де живе проблема.

Якщо вам хочеться додати в Investigation Note все підряд, поставте собі просте запитання: чи допоможе це іншій людині прийняти наступний інженерний крок? Якщо ні — прибирайте. Investigation Note — це не сповідь, а робоча записка.

7. Reviewer-agent як друга пара очей

На цьому етапі дуже приємно повторно використати те, що ви вже зібрали в Workflow Kit. Reviewer-agent потрібен не лише для коду та PR. Він чудово працює як друга пара очей для розслідування. Причому це якраз той випадок, коли subagent особливо доречний: основна сесія зайнята дослідженням, а reviewer отримує вже готовий Investigation Note і перевіряє якість висновків.

Запит тут може бути таким:

Перевір Investigation Note як reviewer.
Для кожного висновку відповідай, чи є під ним evidence.
Якщо evidence слабке або відсутнє, познач це як unknown.
Не пропонуй реалізацію і не редагуй код.

Чим хороший такий крок? По-перше, він не засмічує основну сесію тонною проміжних коментарів. По-друге, fresh-context reviewer часто помічає те, чого writer-сесія вже перестала бачити. Це класичний ефект: коли ви самі довго розслідуєте issue, у вас у голові вже склалася «улюблена версія». Reviewer-agent допомагає перевірити, чи не почали ви випадково видавати цю улюблену версію за факт.

Важливо лише не перекладати на нього відповідальність. Reviewer-agent не виносить вирок. Він підсвічує слабкі місця. Рішення все одно приймаєте ви: чи достатньо evidence, чи можна переходити до плану, де потрібно дооцінити, а де невідомість є допустимою.

8. Дії за наявності невирішених unknowns

Ось тут багато хто вперше видихає й розуміє, що розслідування не зобов’язане давати стовідсоткове знання про світ. Наявність unknowns — не провал. Провал — вдавати, що їх немає. У живих проєктах якісь запитання майже завжди залишаються. Питання лише в тому, які саме.

Якщо unknown стосується косметичної деталі, наприклад тексту повідомлення для frontend, його можна чесно зафіксувати як assumption і окремо прийняти пізніше. Якщо unknown стосується публічного API, shared-методу, схеми даних або прихованого використання сервісу в інших потоках, це вже стоп-лінія. Тут не треба «сподіватися, що все буде нормально». Потрібно або дообстежити, або підняти питання людині, яка володіє цією областю.

Корисно розрізняти два типи невідомості. Перша — робоча, допустима. Наприклад: «frontend очікує один із двох варіантів error code, уточнити під час узгодження». Друга — блокувальна. Наприклад: «незрозуміло, чи використовується calculateTotal() у nightly job, де поведінка на порожньому списку принципово інша». У другому випадку рухатися далі зарано. І це нормально.

Гарне розслідування закінчується не фразою «тепер усе абсолютно ясно», а станом, у якому у вас є читабельна карта: релевантні файли, точки входу, evidence, ризики та чесно позначені unknowns. Код при цьому все ще не змінений ані на рядок. І це чудовий результат. Тому що тепер ви входите до наступного інженерного кроку не з ліхтариком у тумані, а з нормальною картою, на якій уже позначено, де дорога, де болото, а де краще не зрізати шлях, навіть якщо Claude дуже впевнено пропонує «швидко і красиво».

9. Хмарний планувальник як прискорювач

Усе, що ми розбирали вище, — це класичний локальний plan mode: ви самі ведете сесію, читаєте evidence, складаєте Investigation Note. Сучасні версії Claude Code пропонують для того самого сценарію ще один режим — хмарний планувальник із розширеним бюджетом контексту та вбудованою перевіркою плану самим собою. Запускається однією командою (умовно /ultraplan, точна назва й доступність можуть змінюватися від версії до версії). Ментальна модель тут дуже проста: це той самий plan mode, який ми щойно розібрали, але винесений у хмарне середовище, де в агента більше контексту і є вбудований розбір власного плану перед тим, як віддати його вам.

На виході ви отримуєте готовий пакет: Investigation Note, Implementation Plan, список ризиків і стратегію перевірки в одному документі, який уже пройшов внутрішній розбір плану самим планувальником.

Коли хмарний планувальник доречний

Якщо задача зачіпає кілька модулів Commerce OS, і evidence доводиться збирати по великому коду, який локально просто не поміщається в контекст сесії. Ви лише розбираєтеся в проєкті, і звичайній сесії не вистачає контексту, щоб будувати висновки на evidence, а не на здогадках. Потрібен план для зміни з високим ризиком — аутентифікація, платежі, міграції, — і вбудована друга думка виправдовує додаткову затримку.

Розслідування локально займе понад пів години, а хмарний агент тим часом працює паралельно, поки ви готуєте baseline або тести. Нарешті, міграційний discovery — канонічний випадок: там пакет доказів зазвичай великий, changelog, матриця сумісності, граф залежностей, і хмарний контекст тут буквально для цього й потрібен.

Окремо зазначу, що на момент написання цього курсу хмарний планувальник не давав особливої вигоди в плануванні. Скоріше це додатковий спосіб заробити гроші для Anthropic, якщо ви вже користуєтеся підпискою Claude Code. Треба ж вам ще щось продати за гроші :)

Коли хмарний планувальник недоречний

Задача маленька й зрозуміла — накладні витрати на хмарний запуск більші, ніж виграш. Репозиторій або дані не можна вивантажувати в хмарне середовище — це чутливі дані або регульоване середовище, і тоді питання взагалі не в якості плану, а в політиці безпеки, яку ми докладно розбираємо в наступних рівнях курсу. Ви не зможете валідовувати повернений план — це взагалі базове правило: хмарний планувальник не скасовує межу схвалення, а план без розуміння небезпечніший за відсутність плану. І, нарешті, терміновий hotfix — виграш у якості плану не виправдовує затримку.

Дозволи для хмарного запуску — окрема історія, до якої ми ще повернемося в курсі. У хмарного агента окрема модель дозволів: свій білінг, свій журнал аудиту, свій набір дозволених файлів і шляхів. Це має бути явно зафіксовано в командній політиці: які задачі допустимо віддавати в хмарне планування, які — лише локально.

Ключова формула при цьому не змінюється. Хмарний варіант не скасовує межу схвалення. Планувальник пропонує — людина затверджує.

Результат хмарного запуску йде рівно в той самий потік роботи, що й розслідування, зібране локально: ви читаєте план, затверджуєте або коригуєте, передаєте в Implementation Plan (наступна лекція), а звідти — в керовану реалізацію, до якої ми перейдемо в наступному рівні. Хмарний планувальник — це спосіб отримати план швидше й із більшим контекстом, а не спосіб обійти перевірку.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ