Аналіз чужого codebase і документація на доказах
Сьогодні нам треба зайти в чужий, незнайомий проєкт і зрозуміти його. Навчимося:
- читати codebase на доказах, а не на гарний переказ, і збирати робочу карту проєкту;
- будувати карту API та інтеграцій, брати докази з runtime, виносити важке розслідування в subagents і писати документацію, якій можна довіряти.
Рівень 7. Аналіз codebase: discovery, evidence-based Q&A і карта проєкту
Рівень 8. Інтеграції, документація та розслідування через subagents
Міф "поясни проєкт"
Відкрили чужий репозиторій - і рука тягнеться спитати Claude: "поясни, що тут відбувається". У відповідь прийде гарний Markdown, який звучить розумніше, ніж працює.
Широке питання дає надто гладку картину. Claude переказує проєкт як екскурсовод: без "тут не впевнений" і "це не перевіряв". Текст приємний, опори нема. А вам потрібна не екскурсія, а карта:
- стек і фреймворки - щоб розуміти, які файли й патерни взагалі шукати;
- команди запуску, збірки й тестів - щоб не гадати, які команди живі;
- роль тек верхнього рівня - щоб бачити структуру, а не набір випадкових директорій;
- точки входу - щоб розуміти, звідки застосунок стартує;
- що поки неясно - щоб не плутати незнання з розумінням.
Задайте рамку прямо в запиті.
Погано:
Поясни цей проєкт.
Краще:
Зроби перший огляд проєкту.
Знайди: стек і фреймворки, точки входу, команди
запуску й тестів, роль тек верхнього рівня.
Що поки неясно - так і скажи.
Для важливих висновків вкажи файл або команду.
Безпечний старт і перший прохід
Перед дослідженням переконайтеся, що ви в правильному місці й не змішуєте дослідження (discovery) з іншим завданням. Дослідження і правка коду - різні фази, тому тримайте їх окремо: досліджуйте в окремій сесії та в режимі, де ви нічого не змінюєте.
Мінімальна перевірка перед стартом займає три команди:
pwd # чи там ми стоїмо
git status # чи нема чужого хаосу в робочому дереві
ls # що на верхньому рівні проєкту
І ще один бік безпечного старту: репозиторій чужий. Не запускайте наосліп команди встановлення і скрипти з незнайомого проєкту (postinstall, Makefile, build-хуки) - спершу загляньте, що вони роблять.
Брудне дерево легко прийняти за частину архітектури, тому спершу розберіться з ним. далі - перший прохід. Не починайте з випадкових класів і не хапайтеся за найдовший файл. Питання - ті самі, що в рамці з минулого слайда, тільки тепер ви самі дивитеся, де лежать відповіді:
- файли збірки - дають стек і залежності;
- файли запуску - показують, як проєкт оживає;
- теки верхнього рівня - дають першу карту.
І один раз проговоріть Claude межі: "зараз нічого не змінюємо, потрібен лише огляд" - менше ризику, що він побіжить "допомагати".
Чужий проєкт для тренування
Прийоми цього вебінару зручно проганяти на одному живому репозиторії. Беріть будь-який із трьох - або знайдіть на GitHub свій: невеликий, з тестами і зрозумілим README:
- spring-petclinic - канонічний навчальний Spring-проєкт на ~50 файлів: зручний для першої карти і runtime flow;
- spring-boot-realworld-example-app - REST API з JWT-авторизацією, базою і тестами: є що покласти в API_MAP;
- node-express-realworld-example-app - той самий проєкт на Express, якщо ваш стек ближчий до JavaScript.
Claude дослідник, а не оракул
Claude Code звучить переконливо навіть там, де даних мало. Не зі зла - широке питання підштовхує його склеїти правдоподібну історію. Повірите без перевірки - будете лагодити не той модуль і три години шукати баг там, де його нема.
Звідси головне правило рівня: якщо у твердження нема посилання на код, тест, конфіг або вивід команди - це не факт, а гіпотеза. Це не недовіра, а зміна ролі: Claude не оракул, а швидкий помічник-дослідник. Він шукає, підсумовує, зв'язує шматки проєкту, але джерело істини лишається в репозиторії.
Через цю схему проходить кожне питання про проєкт: що підтвердилося файлами - переносимо в нотатки, решта живе як чесно позначена гіпотеза.
Питання, яке зручно перевірити
Частіше проблема не в тому, що Claude помиляється, а в тому, як ви спитали. "Як тут працює auth?" для моделі звучить як "розкажи щось розумне швидше". Сильне питання робить три речі одразу: звужує область пошуку, задає формат під перевірку і окремо просить список припущень.
Ще звичка: одне питання - одна поведінка. Не звалюйте в одне повідомлення логін, повернення і фонові завдання, інакше самі засмічуєте контекст. І просіть не відповідь, а структуру відповіді - її зручно перевіряти блок за блоком. Ось відповідь на питання "хто може створювати статті?" з навчального репозиторію:
## Твердження
Створити статтю через POST /articles може лише
авторизований користувач із JWT-токеном.
## Докази
- api/ArticlesApi.java -> POST /articles, створення статті
- security-конфіг: POST /articles не входить у відкриті маршрути
- тест: запит без токена отримує 401
## Впевненість
високий для HTTP-маршруту, середній для проєкту цілком
(у репозиторії є ще GraphQL-гілка - її не дивилися)
Блок припущень і чесний "середній" рівень - не формальність: у незнайомому проєкті за один прохід завжди лишається неперевірене, і краще це бачити, ніж ховати за бадьорим "високий".
Розмову перетворюємо на артефакт
Discovery, лишений у чаті, за кілька днів тоне в нових обговореннях - лишається відчуття розумної наради без протоколу. Тому перший шар збирайте одразу у файл CODEBASE_INVENTORY.md - робочу карту місцевості: де логіка, як запускати, де тести, що небезпечно чіпати, що ви ще не зрозуміли.
Його легко сплутати з README, але це колеги, а не дублікати - питання в них різні:
README.mdвідповідає "що це і як підняти" - це вхідні двері для нової людини;CODEBASE_INVENTORY.mdвідповідає "як усередині орієнтуватися, щоб щось зрозуміти або змінити" - це план будівлі.
Знайомий з безпечного старту CLAUDE.md - третій сусід у цьому ряду: він підказує агенту, як поводитися в проєкті (стартову версію Claude накидає сам по коду командою /init), тоді як CODEBASE_INVENTORY.md лишається картою для вас - із зонами ризику і відкритими питаннями, яких /init не виводить.
З таким файлом завтра ви не питаєте знову "а де обробка замовлень?". відкрили inventory і за хвилину відновили картину.
Одразу гарний файл не обов'язковий: грубі нотатки в чаті або чернетці - нормальний початок. У CODEBASE_INVENTORY.md переносьте те, що перевірили і хочете зберегти.
Що кладемо в inventory
Робочий inventory (опис проєкту) короткий і насичений: він не переказує код, а допомагає орієнтуватися. Набір розділів стабільний - стек, модулі та їхня відповідальність, точки входу, команди, тести й конфіги, карта залежностей, runtime-потоки, і дві найцінніші секції:
- зони підвищеного ризику -
payments/,migrations/: сюди не можна з настроєм "зараз швиденько підчистимо"; - відкриті питання - те, що ви не вигадали, а чесно позначили як неперевірене.
Головна пастка - писати "надто правильно" і перелічувати класи з методами. Це просто дублює репозиторій, та й годі. Пишіть відповідальність модуля, а не каталог методів: не "OrderService містить 14 методів", а "orders/ - кошик, оформлення, статуси".
# CODEBASE_INVENTORY.md
## Стек і технології
## Модулі та відповідальність
## Точки входу
## Корисні команди
## Тести й конфіги
## Карта залежностей
## Runtime-потоки
## Зони підвищеного ризику
## Відкриті питання
Карта залежностей
Дерево тек створює ілюзію порядку, але теки - це адреси. Вони кажуть "що є", а не "хто кого викликає". Залежності - це вже дорожній рух, і дивитися на них варто в три зрізи.
- зовнішні - маніфест
package.json,build.gradleпоказує, що проєкт хоче, реально встановлені версії живуть у lockfile. Джерело правди - lockfile, не пам'ять Claude; - внутрішні - куди дивляться стрілки між модулями (
ordersзалежить відpayments); - зворотні - хто залежить від модуля, тобто хто впаде, якщо його зачепити.
Зворотні залежності часто важливіші за прямі: файл, на який посилаються кілька модулів, - центральна точка ризику.
Тут видно радіус ураження: маленька правка RefundPolicy.java б'є одразу по чотирьох модулях - такий файл позначають в inventory як ризикований. Цикли й порушення шарів тут лише помічають з evidence, а не лікують у тій самій сесії.
Runtime flow і точки входу
Inventory і карта залежностей - це скелет, а скелет не рухається. Runtime flow (потік виконання) показує, що відбувається, коли система працює. Перший крок - знайти точку входу, і вона не завжди main(): замовлення це HTTP-маршрут, перерахунок метрик - фонове завдання, ініціалізація кешу - стартова логіка.
Далі читайте ланцюжок викликів, а не список файлів: видно, хто кого викликає, де змінюються дані і де побічні ефекти - запис у БД, подія, виклик зовнішнього сервісу. І обов'язково гілка помилки: код частіше ламається саме на ній.
Схема дає порядок (резерв раніше за оплату, оплата раніше за збереження) і розгалуження: нема товару - не йдемо в оплату; не пройшла оплата - замовлення не зберігаємо як успішне. Правило просте: один runtime flow - одна історія, інакше замість слідів отримаєте локшину.
POST /api/orders). Далі запит іде по ланцюжку методів усередині backend.API_MAP.md: куди йде запит
CODEBASE_INVENTORY.md відповідає "що в проєкті є". API_MAP.md відповідає на інше питання - "куди йде запит": через який маршрут входить, де йде в сервіси, коли впирається в базу, коли смикає зовнішній сервіс.
Інтеграція тут - це будь-який важливий стик, що впливає на поведінку, не лише зовнішній. У карту потрапляють:
- HTTP-ендпоінт і контролер - вхідна точка користувацького сценарію;
- внутрішній клієнт (наприклад
StripeClient) - зв'язок із зовнішнім сервісом; - база даних, черга або подія - продовження сценарію;
- межа авторизації - хто взагалі має право дійти до маршруту;
- конфіг середовища і тести - від чого маршрут залежить і чим підтверджується.
Часта плутанина: карта інтеграцій проєкту - це про те, що вже живе в кодовій базі, а не про підключення Claude до зовнішніх інструментів.
Якщо терміни зі списку поки плутаються - ось той самий шлях запиту однією картинкою: згори вхід, далі перевірка прав, потім бізнес-логіка і те, куди сценарій іде далі.
Збираємо 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 - не "міні-розробник" і не розумний стажер, а окреме вікно контексту під вузьке дослідницьке завдання. Його сила не в розумі, а в ізоляції: багато читає, а назовні віддає лише вижимку.
Питання до себе одне: чи потрібно, щоб Claude багато прочитав, але мало повернув? Знайти всі точки виклику Stripe або зібрати тести навколо refund flow - його робота. а прочитати один контролер або уточнити ім'я методу у відкритому файлі - subagent тут зайвий посередник.
Завдання і output contract subagent
Марне розслідування майже завжди від розмитої постановки, а не від поганого Claude: "подивись, що тут із платежами" поверне туман. Тому subagent task оформлюється як маленький task spec (міні-ТЗ на дослідження), а відповідь - як заздалегідь обумовлений формат.
Хороший output contract (той самий обумовлений формат відповіді) майже завжди містить п'ять речей:
- summary - суть у двох рядках;
- evidence - посилання
file:lineдля перевірки; - assumptions - де subagent здогадався, а не побачив;
- open questions - що не зміг підтвердити;
- next steps - що логічно робити далі.
Знайди всі точки, де проєкт працює з JWT-токенами:
створення, перевірка, термін життя, секрети в конфігах.
Дивись лише build file, auth code, config keys, env vars, integration tests.
Поверни: summary, file:line посилання, пов'язані тести, open questions.
Якщо щось схоже на гіпотезу - познач явно. Не змінюй файли.
Назад берете summary і evidence, вибірково перевіряєте два-три опорних місця, і лише потім оновлюєте артефакт. Subagent має стискати дослідження, а не переїжджати разом із шумом у нове місце.
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
Тому документація живе в репозиторії, змінюється через diff і проходить review - навіть якщо ви працюєте сам. Документ приймається не за впевненістю тону і не за тим, як "приємно читається", а за збігом з кодом, конфігами і реальною поведінкою.
Щоб не пропустити очевидне, тримайте поруч короткий чеклист:
- точна - описує те, що є, без прикрашування;
- спирається на джерело - кожне твердження можна тицьнути у файл, конфіг або команду;
- без вигадок - нема класів, флагів і роутів, яких нема в коді;
- команди перевірені - обіцяний
npm startі тести реально запускаються; - допущення названі - де здогад, там чесна позначка;
- обмеження вказані - що не покрито або не перевірено, сказано прямо;
- достатньо повна - вистачає зайти в завдання, без води на сорок екранів;
- diff читабельний - зміну можна перевірити по шматках.
Це рамка для важливої документації; для правки в один рядок вистачає побіжної самоперевірки.
Дві найдешевші перевірки. Перша - запускати команди з документа буквально: текст обіцяє npm start, а package.json знає лише npm run dev - це помилка, а не стиль. Друга - шукати названі класи через grep і find: найвпевненіші галюцинації ховаються в розділах про архітектуру і API, де Claude називає те, чого в коді нема.
Великий diff ріжте на частини - інакше перевіряльник майже неминуче пропустить помилку.
Зібраний ланцюжок
Складіть усе в одну лінію, і видно весь маршрут роботи з чужим проєктом:
- чистий Git-старт і постановка завдання;
- керування контекстом;
CODEBASE_INVENTORY.md- робоча карта проєкту;API_MAP.md- куди йдуть запити;- evidence з рантайму - термінал, trace, IDE;
- документація за збігом із системою.
Для невеликого завдання беруть 2-3 потрібних кроки і йдуть. Повний шлях розгортають на великому або незнайомому проєкті. Іноді й порядок інший: спершу швидкий прототип або гіпотеза, а карта з документацією - потім.
Наскрізна звичка двох рівнів одна: Claude швидко шукає, підсумовує і зв'язує, але право сказати "цьому можна довіряти" лишається за вами. А коли бачите, що одні й ті самі ручні кроки повторюються з проєкту в проєкт - зібрати evidence, оновити артефакт, перевірити команди, прийняти diff - це сигнал, що їх пора пакувати в повторно використовувані ассети. Про це далі.
Практика 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 чужого коду, потім інженерне рішення - чинити точково чи переписати за контрактом. Заборонений лише один варіант: "перепишу все навмання" - рішення без аудиту.
Haiku 50: повні вимоги
Це ТЗ, яке кіт дизайнера... не те щоб читав. Звіряйте з ним знахідки аудиту: що виконано, що лише виглядає виконаним, чого нема зовсім. Вимог небагато, і кожна тут по ділу:
- OpenAI API викликається лише з бекенду, API-ключ не потрапляє у фронтенд (сам ключ дамо в чаті групи);
- треба підтримати 12 мов; обрана мова йде в запит і промпт;
- поле ключових слів не очищається після генерації; для очищення потрібна окрема кнопка;
- валідація: менше 3 слів або більше 7, порожня мова, недоступний сервер або OpenAI API - на кожен випадок зрозуміла помилка;
- кнопка
50 васабіз іконкою васабі підвищуєРівень гостротивід 0 до 6; - рівень гостроти керує грайливістю, абсурдом і непередбачуваністю тексту;
- застосунок не допускає мат, агресію або заборонений контент;
- історія зберігає останні 100 генерацій у браузері без бази даних. Серверне in-memory-сховище (дані живуть в оперативній пам'яті) можна використовувати лише як додаткову опцію, але не як основну вимогу;
- інтерфейс максимально мінімалістичний, бажано у стилі Bento Grid.
Бекенд написаний на Node.js без залежностей. Чинити його чи переписати - вирішуйте за результатами аудиту.
Переписувати можна на будь-якому стеку (Node.js, Python, Kotlin, Java), аби приймав запит фронтенду і ходив в OpenAI API. І одразу про межі: не потрібні база даних, авторизація, реєстрація, мобільний застосунок і аналізатор складів - спочатку маленький застосунок, який чесно працює.
На схемі видно головний поділ: frontend перевіряє ввід і зберігає історію, backend тримає API-ключ, модель і промпт, OpenAI API лише генерує хайку.
Haiku 50: спадок від кота дизайнера
Ось і спадок. Кіт спробував васабі передав архів проєкту: HTML/CSS/JS-макет, server.js і readme.txt у жанрі "лапки заважають". Виглядає як застосунок - але виглядає не означає виконує ТЗ. Тому почніть не з правок, а з аудиту: вивчіть проєкт як чужий codebase, а не як картинку.
Перед першою правкою попросіть Claude зібрати короткий HANDOFF_REVIEW.md: що вже працює, що лише виглядає готовим, які вимоги не закриті і чим це підтверджується у файлах.
- структура файлів, стани UI, обробники і робота з
localStorage- де логіка вже є; - мови: скільки з 12 реально працюють;
- кнопки й обробники: чи всі кнопки до чогось прив'язані;
- зв'язка фронт-бекенд: куди насправді йде запит при натисканні "Згенерувати" (підказка: вкладка Network у DevTools);
- mock/fallback (заглушки і запасні відповіді) - і чи не маскують вони помилки;
- історія: останні 100 генерацій у браузері, а не на сервері;
- безпека: де живе API-ключ і що там із моделлю з ТЗ.
Не переписуйте дизайн з нуля - переданий макет зберігається. А от серверну частину чиніть або перескладайте за результатами аудиту: зв'язка з бекендом, OpenAI API, валідація, історія, обробка помилок. Будь-яку розбіжність із ТЗ спершу фіксуємо в HANDOFF_REVIEW, потім виправляємо.
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-контракт, обробка помилок і що з котячого коду залишаємо, а що перескладаємо. Потім окремими кроками: бекенд, зв'язка фронт-бекенд, перевірка сценаріїв.
- передавайте в промпт окремі поля
language,wordsіwasabiLevel, а не один склеєний рядок; - попросіть винести обрану модель (
gpt-5-nano-2025-08-07абоgpt-5.6-luna) в одне місце на сервері; - ключ OpenAI перенесіть із коду в змінну середовища (файл
.env), а сам.envдодайте в.gitignore- у код, репозиторій і чат агенту він потрапляти не повинен; - валідацію з брифу дублюйте на сервері, а не лише в браузері: фронтенд легко обійти, тому надійна перевірка живе на бекенді;
- обробку помилок із брифу проженіть окремим кроком, а не впереміш з основним сценарієм.
Промпти проєктуються у два шари:
- базовий шар - 3 рядки, обрана мова, слова користувача, лаконічність, поетичність і жодних пояснень після тексту;
- шар гостроти - рівні 0-6 від спокійного класичного хайку до гострого, сюрреалістичного, але безпечного результату;
- безпека - без мату, агресії і забороненого контенту;
- формат - сиру відповідь спершу нормалізуємо. Модель нерідко обгортає текст у markdown-блок
```Text```або додає вступ на кшталт "Ось ваше хайку". Зріжте обгортку і зайве на бекенді, і тільки потім перевіряйте, що лишилося рівно 3 рядки - якщо ні, показуємо помилку або просимо модель виправити формат.
І ще про промпти: самі тексти тримайте окремо від коду - в окремому файлі або константах. Тоді міняти їх можна в одному місці, як і ім'я моделі.
gpt-5 є два прості важелі. reasoning_effort - для хайку вистачить low або medium: глибоке міркування тут зайве, зате швидше і дешевше. verbosity зі значенням low дає коротку відповідь без зайвої прози, рівно як просить бриф - 3 рядки і нічого навколо. Не впевнені у значеннях - згодуйте LLM сторінки доків і спитайте, що обрати: про reasoning і про нові параметри gpt-5.