Аналіз чужого codebase і документація на доказах

Сьогодні нам треба зайти в чужий, незнайомий проєкт і зрозуміти його. Навчимося:

Сьогодні на вебінарі пройдемо 2 рівні курсу:
Рівень 7. Аналіз codebase: discovery, evidence-based Q&A і карта проєкту
Рівень 8. Інтеграції, документація та розслідування через subagents

Міф "поясни проєкт"

Відкрили чужий репозиторій - і рука тягнеться спитати Claude: "поясни, що тут відбувається". У відповідь прийде гарний Markdown, який звучить розумніше, ніж працює.

Широке питання дає надто гладку картину. Claude переказує проєкт як екскурсовод: без "тут не впевнений" і "це не перевіряв". Текст приємний, опори нема. А вам потрібна не екскурсія, а карта:

Задайте рамку прямо в запиті.

Погано:
Поясни цей проєкт.

Краще:
Зроби перший огляд проєкту.
Знайди: стек і фреймворки, точки входу, команди
запуску й тестів, роль тек верхнього рівня.
Що поки неясно - так і скажи.
Для важливих висновків вкажи файл або команду.
Краще один раз побачити: візьміть живий репозиторій - варіанти на наступному слайді - і прожените обидва промпти поспіль. Першу екскурсію Claude запросто розкаже з пам'яті, навіть не відкривши файли; друга рамка змусить показати, де що лежить. Ця різниця - тема всього вебінару.

Безпечний старт і перший прохід

Перед дослідженням переконайтеся, що ви в правильному місці й не змішуєте дослідження (discovery) з іншим завданням. Дослідження і правка коду - різні фази, тому тримайте їх окремо: досліджуйте в окремій сесії та в режимі, де ви нічого не змінюєте.

Мінімальна перевірка перед стартом займає три команди:

pwd          # чи там ми стоїмо
git status   # чи нема чужого хаосу в робочому дереві
ls           # що на верхньому рівні проєкту

І ще один бік безпечного старту: репозиторій чужий. Не запускайте наосліп команди встановлення і скрипти з незнайомого проєкту (postinstall, Makefile, build-хуки) - спершу загляньте, що вони роблять.

Брудне дерево легко прийняти за частину архітектури, тому спершу розберіться з ним. далі - перший прохід. Не починайте з випадкових класів і не хапайтеся за найдовший файл. Питання - ті самі, що в рамці з минулого слайда, тільки тепер ви самі дивитеся, де лежать відповіді:

І один раз проговоріть Claude межі: "зараз нічого не змінюємо, потрібен лише огляд" - менше ризику, що він побіжить "допомагати".

Чужий проєкт для тренування

Прийоми цього вебінару зручно проганяти на одному живому репозиторії. Беріть будь-який із трьох - або знайдіть на GitHub свій: невеликий, з тестами і зрозумілим README:

Discovery не марафон "хто більше файлів відкриє". Мета першого проходу - орієнтація, а не повне знання; повного не буває навіть у того, хто писав проєкт рік тому.

Claude дослідник, а не оракул

Claude Code звучить переконливо навіть там, де даних мало. Не зі зла - широке питання підштовхує його склеїти правдоподібну історію. Повірите без перевірки - будете лагодити не той модуль і три години шукати баг там, де його нема.

LLM can make mistakes, so double-check outputs

Звідси головне правило рівня: якщо у твердження нема посилання на код, тест, конфіг або вивід команди - це не факт, а гіпотеза. Це не недовіра, а зміна ролі: Claude не оракул, а швидкий помічник-дослідник. Він шукає, підсумовує, зв'язує шматки проєкту, але джерело істини лишається в репозиторії.

flowchart TD A[Питання про проєкт] --> B[Відповідь Claude] B --> C{Є посилання на код, тест чи конфіг?} C -->|ні| D[Вважаємо гіпотезою] C -->|так| E[Відкриваємо файл і перевіряємо] E --> F[Підтверджений вивід у нотатки]

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


Питання, яке зручно перевірити

Частіше проблема не в тому, що Claude помиляється, а в тому, як ви спитали. "Як тут працює auth?" для моделі звучить як "розкажи щось розумне швидше". Сильне питання робить три речі одразу: звужує область пошуку, задає формат під перевірку і окремо просить список припущень.

Ще звичка: одне питання - одна поведінка. Не звалюйте в одне повідомлення логін, повернення і фонові завдання, інакше самі засмічуєте контекст. І просіть не відповідь, а структуру відповіді - її зручно перевіряти блок за блоком. Ось відповідь на питання "хто може створювати статті?" з навчального репозиторію:

## Твердження
Створити статтю через POST /articles може лише
авторизований користувач із JWT-токеном.

## Докази
- api/ArticlesApi.java -> POST /articles, створення статті
- security-конфіг: POST /articles не входить у відкриті маршрути
- тест: запит без токена отримує 401

## Впевненість
високий для HTTP-маршруту, середній для проєкту цілком
(у репозиторії є ще GraphQL-гілка - її не дивилися)

Блок припущень і чесний "середній" рівень - не формальність: у незнайомому проєкті за один прохід завжди лишається неперевірене, і краще це бачити, ніж ховати за бадьорим "високий".

Повний формат - для важливих і ризикованих питань: права доступу, гроші, незнайомий модуль. Для дрібного "як називається цей метод?" вистачить короткої відповіді з посиланням на файл. Калібруйте за ціною помилки.

Розмову перетворюємо на артефакт

Discovery, лишений у чаті, за кілька днів тоне в нових обговореннях - лишається відчуття розумної наради без протоколу. Тому перший шар збирайте одразу у файл CODEBASE_INVENTORY.md - робочу карту місцевості: де логіка, як запускати, де тести, що небезпечно чіпати, що ви ще не зрозуміли.

Його легко сплутати з README, але це колеги, а не дублікати - питання в них різні:

Знайомий з безпечного старту CLAUDE.md - третій сусід у цьому ряду: він підказує агенту, як поводитися в проєкті (стартову версію Claude накидає сам по коду командою /init), тоді як CODEBASE_INVENTORY.md лишається картою для вас - із зонами ризику і відкритими питаннями, яких /init не виводить.

З таким файлом завтра ви не питаєте знову "а де обробка замовлень?". відкрили inventory і за хвилину відновили картину.

Одразу гарний файл не обов'язковий: грубі нотатки в чаті або чернетці - нормальний початок. У CODEBASE_INVENTORY.md переносьте те, що перевірили і хочете зберегти.


Що кладемо в inventory

Робочий inventory (опис проєкту) короткий і насичений: він не переказує код, а допомагає орієнтуватися. Набір розділів стабільний - стек, модулі та їхня відповідальність, точки входу, команди, тести й конфіги, карта залежностей, runtime-потоки, і дві найцінніші секції:

Головна пастка - писати "надто правильно" і перелічувати класи з методами. Це просто дублює репозиторій, та й годі. Пишіть відповідальність модуля, а не каталог методів: не "OrderService містить 14 методів", а "orders/ - кошик, оформлення, статуси".

# CODEBASE_INVENTORY.md
## Стек і технології
## Модулі та відповідальність
## Точки входу
## Корисні команди
## Тести й конфіги
## Карта залежностей
## Runtime-потоки
## Зони підвищеного ризику
## Відкриті питання
Не заповнюйте всі розділи одразу. Dependency map і Runtime flows на першому проході часто порожні - і це нормально: inventory росте разом із розумінням проєкту.
Просто зараз, якщо навчальний репозиторій склоновано: попросіть Claude заповнити по ньому три секції - стек, точки входу, корисні команди - і подивіться, що він чесно лишив у "Відкритих питаннях". Це ваш перший живий inventory за п'ять хвилин.

Карта залежностей

Дерево тек створює ілюзію порядку, але теки - це адреси. Вони кажуть "що є", а не "хто кого викликає". Залежності - це вже дорожній рух, і дивитися на них варто в три зрізи.

Зворотні залежності часто важливіші за прямі: файл, на який посилаються кілька модулів, - центральна точка ризику.

flowchart TD O[orders] --> RP[RefundPolicy.java] P[payments] --> RP S[support] --> RP A[admin] --> RP RP --> R{Торкнулися одного файлу} R --> Z[Зачепили одразу 4 модулі]

Тут видно радіус ураження: маленька правка RefundPolicy.java б'є одразу по чотирьох модулях - такий файл позначають в inventory як ризикований. Цикли й порушення шарів тут лише помічають з evidence, а не лікують у тій самій сесії.

Є LSP або пошук references - пришвидшать карту. Але не перетворюйте discovery на експедицію з налаштування інструментів: на першому проході вистачає читання імпортів і звичайного пошуку.

Runtime flow і точки входу

Inventory і карта залежностей - це скелет, а скелет не рухається. Runtime flow (потік виконання) показує, що відбувається, коли система працює. Перший крок - знайти точку входу, і вона не завжди main(): замовлення це HTTP-маршрут, перерахунок метрик - фонове завдання, ініціалізація кешу - стартова логіка.

Далі читайте ланцюжок викликів, а не список файлів: видно, хто кого викликає, де змінюються дані і де побічні ефекти - запис у БД, подія, виклик зовнішнього сервісу. І обов'язково гілка помилки: код частіше ламається саме на ній.

flowchart TD A[POST /api/orders] --> B[OrderController#create] B --> C[OrderService#placeOrder] C --> D[InventoryService#reserve] D -->|товар є| E[PaymentService#authorize] D -->|товару нема| X[Відповідь 409, замовлення не створено] E -->|оплата успішна| F[OrderRepository#save] E -->|помилка оплати| Y[Замовлення не підтверджено] F --> G[(PostgreSQL)] F --> H[OrderPlacedEvent для сповіщень]

Схема дає порядок (резерв раніше за оплату, оплата раніше за збереження) і розгалуження: нема товару - не йдемо в оплату; не пройшла оплата - замовлення не зберігаємо як успішне. Правило просте: один runtime flow - одна історія, інакше замість слідів отримаєте локшину.

endpoint - це HTTP-адреса, за якою в застосунок приходить запит (наприклад POST /api/orders). Далі запит іде по ланцюжку методів усередині backend.
Просто зараз на навчальному репозиторії: попросіть простежити один такий маршрут - створення статті в realworld або візиту в petclinic - і звірте дві-три ланки ланцюжка з кодом руками.

API_MAP.md: куди йде запит

CODEBASE_INVENTORY.md відповідає "що в проєкті є". API_MAP.md відповідає на інше питання - "куди йде запит": через який маршрут входить, де йде в сервіси, коли впирається в базу, коли смикає зовнішній сервіс.

Інтеграція тут - це будь-який важливий стик, що впливає на поведінку, не лише зовнішній. У карту потрапляють:

Часта плутанина: карта інтеграцій проєкту - це про те, що вже живе в кодовій базі, а не про підключення Claude до зовнішніх інструментів.

MCP (спосіб підключати до Claude зовнішні інструменти - наприклад, читати завдання прямо з трекера) - це інше і розбирається пізніше. Тут мова про інтеграції всередині самого проєкту.

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

flowchart TD U["Користувач / веб-клієнт"] --> EP["HTTP-ендпоінт і контролер - вхідні двері запиту"] EP --> AUTH{"Межа авторизації - пускати далі?"} AUTH -->|ні| STOP["Відмова 401 / 403"] AUTH -->|так| SVC["Сервіс - бізнес-логіка сценарію"] SVC --> EXT["Внутрішній клієнт, напр. StripeClient - зв'язок із зовнішнім сервісом"] SVC --> DB[("База даних - зберегти результат")] SVC --> Q["Черга або подія - продовження сценарію"] CFG["Конфіг середовища і тести - залежності і перевірка"] -.->|впливає| SVC

Збираємо API_MAP з доказами

Хороший API_MAP.md короткий і перевірний: по рядку на ключовий маршрут, а не енциклопедія на сорок екранів. І кожен рядок збирається з джерел, а не з фрази "Claude підсумував": метод і шлях, обробник, авторизація, інтеграції, конфіг, тести й окрема колонка з відкритими питаннями.

Остання колонка дисциплінує: не знайшли підтвердження - пишемо "не перевірено", а не "напевно, використовується мобільним клієнтом, так же логічно".

Веб-клієнт
   |
POST /api/orders        (авторизація: customer session)
   |
OrderController#create
   |
OrderService#createOrder
   |--> StripeClient            // зовнішній платіжний сервіс
   |--> OrderEventPublisher     // подія в чергу order-events
   |--> PostgreSQL              // збереження замовлення

Конфіг: STRIPE_API_KEY, QUEUE_URL
Тест:   OrderControllerTest#create_returns400_forEmptyCart

Розберіть так три-чотири ключових маршрути - і не доведеться згадувати, де платежі, де події, а де просто HTTP-обгортка.


Subagent: окреме вікно для розслідування

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

Subagent - не "міні-розробник" і не розумний стажер, а окреме вікно контексту під вузьке дослідницьке завдання. Його сила не в розумі, а в ізоляції: багато читає, а назовні віддає лише вижимку.

flowchart TD A[Основна сесія] -->|mini task spec| B["Subagent: окреме вікно"] B --> C[Читає багато файлів, тестів, логів] C -->|summary + evidence| D[Основна сесія] D --> E[Перевіряє 2-3 опорних місця] E --> F[Оновлює API_MAP або docs]

Питання до себе одне: чи потрібно, щоб Claude багато прочитав, але мало повернув? Знайти всі точки виклику Stripe або зібрати тести навколо refund flow - його робота. а прочитати один контролер або уточнити ім'я методу у відкритому файлі - subagent тут зайвий посередник.

Subagent глибше - ролі, свої інструменти, ізоляція - розбирається на наступних рівнях. Тут потрібна одна навичка: винести важке читання з основної сесії і отримати назад короткий перевірний результат.

Завдання і output contract subagent

Марне розслідування майже завжди від розмитої постановки, а не від поганого Claude: "подивись, що тут із платежами" поверне туман. Тому subagent task оформлюється як маленький task spec (міні-ТЗ на дослідження), а відповідь - як заздалегідь обумовлений формат.

Хороший output contract (той самий обумовлений формат відповіді) майже завжди містить п'ять речей:

Знайди всі точки, де проєкт працює з JWT-токенами:
створення, перевірка, термін життя, секрети в конфігах.
Дивись лише build file, auth code, config keys, env vars, integration tests.
Поверни: summary, file:line посилання, пов'язані тести, open questions.
Якщо щось схоже на гіпотезу - познач явно. Не змінюй файли.

Назад берете summary і evidence, вибірково перевіряєте два-три опорних місця, і лише потім оновлюєте артефакт. Subagent має стискати дослідження, а не переїжджати разом із шумом у нове місце.

Для швидкої розвідки вистачає одного рядка: "знайди всі точки роботи з JWT, поверни file:line". Повний контракт з assumptions і next steps окупається, коли розслідування велике і результат піде в артефакт або до колеги.

Claude пише чернетку, не істину

Тепер документацію є з чого збирати: CODEBASE_INVENTORY.md, API_MAP.md, звичка перевіряти по коду, evidence з рантайму. Документ збирається з підтверджених артефактів, а не з пам'яті і гарного переказу.

Але тут головна пастка - та сама, що на початку вебінару, тільки в документації переконливий тон застигає як факт: Claude опише модуль, якого нема, вигадає правдоподібну команду запуску, згадає "логічну" інтеграцію. AI-документація без перевірки - це ввічлива галюцинація. Правило уроку: усе, що згенерував Claude, - чернетка, поки ви не звірили текст із кодом, конфігами, командами і тестами.

Якість починається не з формулювання, а з джерел: дайте API_MAP.md, конкретні класи і тести, забороніть вигадувати нове і попросіть відділяти факти від припущень. І пам'ятайте правило "один документ - одне завдання": "onboarding для локального запуску" дає результат, а "задокументуй усе" - ні.

# Потік повернення коштів
Запит створюється через POST /api/orders/{id}/refund (handler: OrderController),
далі RefundService. Повернення вище ліміту отримують статус PENDING_REFUND_REVIEW.

## Що перевірено
- API_MAP.md, OrderController.java, RefundService.java, RefundServiceTest.java

## Обмеження
- webhook платіжного провайдера локально не приходить автоматично

Документація проходить через diff

Поганий метод ламає програму. Поганий README ламає людину, яка намагається її запустити.

Тому документація живе в репозиторії, змінюється через diff і проходить review - навіть якщо ви працюєте сам. Документ приймається не за впевненістю тону і не за тим, як "приємно читається", а за збігом з кодом, конфігами і реальною поведінкою.

Щоб не пропустити очевидне, тримайте поруч короткий чеклист:

Це рамка для важливої документації; для правки в один рядок вистачає побіжної самоперевірки.

flowchart TD D[AI draft] --> F[Diff у репозиторії] F --> V[Перевірка по коду, конфігам, командам] V --> C{Збігається з проєктом?} C -->|ні| R[Правки або позначка здогаду] R --> V C -->|так| A[Документ прийнято]

Дві найдешевші перевірки. Перша - запускати команди з документа буквально: текст обіцяє npm start, а package.json знає лише npm run dev - це помилка, а не стиль. Друга - шукати названі класи через grep і find: найвпевненіші галюцинації ховаються в розділах про архітектуру і API, де Claude називає те, чого в коді нема.

Великий diff ріжте на частини - інакше перевіряльник майже неминуче пропустить помилку.


Зібраний ланцюжок

Складіть усе в одну лінію, і видно весь маршрут роботи з чужим проєктом:

  1. чистий Git-старт і постановка завдання;
  2. керування контекстом;
  3. CODEBASE_INVENTORY.md - робоча карта проєкту;
  4. API_MAP.md - куди йдуть запити;
  5. evidence з рантайму - термінал, trace, IDE;
  6. документація за збігом із системою.

Для невеликого завдання беруть 2-3 потрібних кроки і йдуть. Повний шлях розгортають на великому або незнайомому проєкті. Іноді й порядок інший: спершу швидкий прототип або гіпотеза, а карта з документацією - потім.

Наскрізна звичка двох рівнів одна: Claude швидко шукає, підсумовує і зв'язує, але право сказати "цьому можна довіряти" лишається за вами. А коли бачите, що одні й ті самі ручні кроки повторюються з проєкту в проєкт - зібрати evidence, оновити артефакт, перевірити команди, прийняти diff - це сигнал, що їх пора пакувати в повторно використовувані ассети. Про це далі.

Увесь цей ланцюжок артефактів - меню під завдання, а не ритуал щоразу. І пам'ятайте: гарна карта або документ трохи неповні, але чесні, надійніші за повні, красиві і місцями вигадані - особливо якщо хочете, щоб Claude використовував файл як контекст, а не як збірник легенд.

Практика Haiku 50

Веб-застосунок, який генерує хайку через OpenAI API. Хайку - це короткий японський вірш із трьох рядків: момент, образ, настрій, лаконічність і поетичність. Суворий лічильник складів 5-7-5 тут не потрібен.

Користувач вводить 3-7 ключових слів або коротких фраз через кому, обирає мову генерації (набір популярних) і натискає Згенерувати хайку. Для роботи можна обрати одну з двох доступних моделей OpenAI: gpt-5-nano-2025-08-07 або gpt-5.6-luna.

Дві речі роблять проєкт собою. Кнопка 50 васабі піднімає Рівень гостроти від 0 до 6 - від спокійної класики до гострого, майже абсурдного тексту. А історія зберігає останні 100 генерацій локально в браузері.

Проєкт дістається вам не з нуля

кіт дизайнера навайбкодив і симпатичний UI, і бекенд на Node.js. Каже, у нього на компі ніби працює, але не точно - лапки заважають. Вам передають архів цілком, і на перший погляд усе справді живе: сервер стартує, хайку генеруються, історія зберігається.

Розберіться з кодом від кота дизайнера - і доведіть застосунок до стану, коли він чесно виконує ТЗ із наступного слайда. Спершу inventory і runtime flow чужого коду, потім інженерне рішення - чинити точково чи переписати за контрактом. Заборонений лише один варіант: "перепишу все навмання" - рішення без аудиту.

Токен OpenAI - це гроші на вашому рахунку. Витече в публічний репозиторій на GitHub - його автоматично заблокують, зазвичай у межах 20 хвилин. Кіт, до речі, на ці граблі вже наступив - знайдете під час аудиту.

Haiku 50: повні вимоги

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

Бекенд написаний на Node.js без залежностей. Чинити його чи переписати - вирішуйте за результатами аудиту.

Переписувати можна на будь-якому стеку (Node.js, Python, Kotlin, Java), аби приймав запит фронтенду і ходив в OpenAI API. І одразу про межі: не потрібні база даних, авторизація, реєстрація, мобільний застосунок і аналізатор складів - спочатку маленький застосунок, який чесно працює.

flowchart LR U["Користувач"] --> UI["Frontend UI"] UI --> V{"Ввід валідний?"} V -->|ні| E["Показати помилку"] V -->|так| R["POST: words, language, wasabiLevel"] R --> B["Backend: ключ, модель, промпт"] B --> O["OpenAI API"] O --> UI UI --> H["localStorage: останні 100"]

На схемі видно головний поділ: frontend перевіряє ввід і зберігає історію, backend тримає API-ключ, модель і промпт, OpenAI API лише генерує хайку.


Haiku 50: спадок від кота дизайнера

Ось і спадок. Кіт спробував васабі передав архів проєкту: HTML/CSS/JS-макет, server.js і readme.txt у жанрі "лапки заважають". Виглядає як застосунок - але виглядає не означає виконує ТЗ. Тому почніть не з правок, а з аудиту: вивчіть проєкт як чужий codebase, а не як картинку.

Перед першою правкою попросіть Claude зібрати короткий HANDOFF_REVIEW.md: що вже працює, що лише виглядає готовим, які вимоги не закриті і чим це підтверджується у файлах.

Не переписуйте дизайн з нуля - переданий макет зберігається. А от серверну частину чиніть або перескладайте за результатами аудиту: зв'язка з бекендом, OpenAI API, валідація, історія, обробка помилок. Будь-яку розбіжність із ТЗ спершу фіксуємо в HANDOFF_REVIEW, потім виправляємо.

Хороший перший результат - не код, а список gaps з evidence. Після нього агенту простіше давати маленькі завдання, а вам простіше зрозуміти, що саме він поміняв.

Haiku 50: опора для реалізації

Робите такий проєкт уперше? Тоді це ваш слайд. Тільки спершу завершіть аудит, а потім подивіться сюди.

Почніть не з кнопок, а з межі між фронтендом і сервером. Котячий server.js уже оголошує такий endpoint - звірте, що він реально приймає і повертає, а не що має за контрактом:

POST /generate-haiku

request:
words: string[]             // 3-7 ключових слів або коротких фраз
language: string            // одна з 12 мов
wasabiLevel: number         // 0-6

response:
haiku: string               // рівно 3 рядки

З агентом краще йти шарами. Спочатку - цільова картинка без коду: API-контракт, обробка помилок і що з котячого коду залишаємо, а що перескладаємо. Потім окремими кроками: бекенд, зв'язка фронт-бекенд, перевірка сценаріїв.

Промпти проєктуються у два шари:

І ще про промпти: самі тексти тримайте окремо від коду - в окремому файлі або константах. Тоді міняти їх можна в одному місці, як і ім'я моделі.

Під це завдання у gpt-5 є два прості важелі. reasoning_effort - для хайку вистачить low або medium: глибоке міркування тут зайве, зате швидше і дешевше. verbosity зі значенням low дає коротку відповідь без зайвої прози, рівно як просить бриф - 3 рядки і нічого навколо. Не впевнені у значеннях - згодуйте LLM сторінки доків і спитайте, що обрати: про reasoning і про нові параметри gpt-5.