Нарахування очок полагодили. У відповіді лежать вивід термінала, скриншот табло і коротке "готово", файлів багато, а запитання просте: що з цього відповідає на вимогу завдання?
Свідчення - це не будь-який файл, який опинився поруч із виправленням. Це результат конкретної перевірки, з якого видно, що перевіряли, на якому стані коду і що в підсумку вийшло. Різні матеріали відповідають на різні запитання, і жоден не відповідає на всі одразу.
Розберемо, як перетворити вимогу на твердження, яке можна перевірити; що записати про прогін команди; що підтверджує лог, що diff і що кадр екрана. Потім складемо це в короткий журнал EVIDENCE_LOG із шести полів і перевіримо, чи досить готового набору матеріалів.

Критерій задає перевірку
Наскрізний приклад на всю статтю: невелика бонус-гра з рахунком на табло. На старті рахунок 0, три збіги мають додавати 3 очки, а до виправлення додавали 30. Правило нарахування придумане для цієї гри - в сусідньому проєкті воно може бути будь-яким, переносити його туди не варто.
Фразу "рахунок виправлено" перевірити не можна. Що запускати, на що дивитися? Незрозуміло. Твердження, яке можна перевірити, складається з трьох частин: початковий стан, дія і очікуване спостереження. Виходить "якщо рахунок 0, три збіги додають 3 очки, і на табло видно 3". Тепер твердження має перевірку.
Далі це твердження розпадається на окремі спостереження. Розрахунок і те, що бачить гравець, - різні речі, і підтвердження для них потрібні різні. Третій рядок таблиці - про нарахування в лідерборді: такої вимоги в завданні може й не бути, але якщо вона є, для неї потрібне своє спостереження.
| Критерій | Чим підтверджується | Межа висновку |
|---|---|---|
| розрахунок: три збіги з нуля дають 3 очки | прогін тесту на виправленому коді з назвою тесту й підсумком | свідчить про перевірений сценарій у коді, але не про те, що бачить гравець |
| інтерфейс: після трьох збігів на табло 3 | запис відтвореного сценарію разом із кадром екрана | підтверджує видиме число, але не пояснює, звідки воно взялося |
| результат зберігається в лідерборді | окремий сценарій, у якому збережене значення зчитали ще раз | кадром табло не підтверджується взагалі; без такого сценарію пункт лишається неперевіреним |
Третій стовпець тут найкорисніший. Свідчення майже завжди підтверджує менше, ніж хочеться, і межа проходить там, де закінчується виконана дія. У нашому прикладі тест розрахунку не перевіряє табло, а кадр табло не показує змінений рядок коду.
І тримайте окремо дві речі: вимога - це те, що має бути правдою наприкінці, а результат - те, що ви фактично отримали. Коли вони змішуються в одному абзаці, "має додавати 3" непомітно перетворюється на "додає 3", хоча ніхто нічого не запускав.
Команда і її результат
Прогін перевірки описують п'ять речей. Жодна з них не очевидна тому, хто повторюватиме перевірку за тиждень (навіть якщо це будете ви):
- тека, з якої запускали команду;
- сама команда, дослівно;
- стан коду: до правки, після правки, з якими незакоміченими змінами;
- чим закінчилося: код виходу і підсумкові лічильники;
- які перевірки справді брали участь, а які ні.
Окремо варто розрізняти "треба запустити npm test" і "запустив npm test, ось вивід". Перше - інструкція, план на майбутнє. Друге - факт. Саме тут легко видати намір за результат, особливо коли у відповіді акуратно розписано, що варто було б перевірити.
npm test не запускає "всі тести взагалі". Він виконує те, що записано в полі test розділу scripts конкретного package.json - того npm-проєкту, який обрано. Щоб не гадати, який саме, запускайте команду з його кореня і записуйте цю теку в журнал. У сусідньому проєкті за тією самою назвою може стояти інший інструмент, інший набір кроків або нічого.
Команда закінчується кодом виходу: 0 зазвичай означає "інструмент вважає прогін успішним". У bash його показує echo $? одразу після команди; у PowerShell для зовнішньої програми на кшталт npm це $LASTEXITCODE. Тільки от нуль не каже, що потрібний тест брав участь: його могли пропустити, відфільтрувати за назвою або взагалі не написати. Тому поруч із кодом виходу завжди потрібні лічильники й назва тесту, який вас цікавить.
Просіть показати фактичний запуск: команду, теку і оригінальний вивід повністю, а окремим рядком - що із запланованого виконати не вдалося. Команду беріть із проєкту, а не із загальної шпаргалки: у package.json видно, що саме ховається за npm test у цьому проєкті.
Що зберегти з логу
Вивід прогону буває довгим, і повністю в журнал його ніхто не переносить. У короткий фрагмент потрапляють чотири речі: назва тесту, що впав, очікуване й фактичне значення, причина падіння і підсумкові лічильники. Решта живе у файлі, на який ви поставите посилання. Нижче скорочений навчальний приклад виводу, а не запис виконаного запуску.
✖ three matches give 3 points (2.4108ms)
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
30 !== 3
at TestContext.<anonymous> (src/bonus-game/score.test.js:8:10)
ℹ tests 1
ℹ pass 0
ℹ fail 1
ℹ skipped 0Це фрагмент, повний вивід збережено у файл, скажімо logs/test-fail.txt. З цього фрагмента вже видно головне: упав саме тест про три збіги, очікували 3, отримали 30, пропущених перевірок немає.
Оригінальний вивід потрапляє в журнал як є. Переказ своїми словами (напр. "тест упав через неправильний множник") здається зрозумілішим, але це вже висновок, а не спостереження, і перевірити його за журналом не можна. Тримайте одне поруч з іншим: спершу рядки інструмента, потім ваше пояснення.
Адреса в рядку стектрейсу - це місце, де спрацювала перевірка, тобто файл тесту. Причину шукають у коді гри, і знайдений там множник - результат читання коду, а не рядок із логу. У журналі ці два джерела підписують по-різному, інакше потім не розібратися, звідки взялося число 10.
Що підтверджує diff
Diff показує різницю між двома станами файлу. Він не каже, що код після правки бодай раз запускали (про запуски diff узагалі нічого не знає), і тим паче не каже, що поведінка змінилася так, як ви розраховували.
--- a/src/bonus-game/score.js
+++ b/src/bonus-game/score.js
@@ -1,5 +1,5 @@
-const POINTS_PER_MATCH = 10;
+const POINTS_PER_MATCH = 1;
function calcScore(matches) {
return matches * POINTS_PER_MATCH;
}Під таким фрагментом потрібен один рядок підпису: які стани порівняли. Наприклад "робоче дерево проти коміту a1b2c3d до правки, команда git diff HEAD"; ідентифікатор тут навчальний, у журналі потрібен ваш справжній. Така команда порівнює поточні відстежувані файли з HEAD, включно з підготовленими до коміту змінами. Звичайний git diff без HEAD показує тільки різницю з підготовленим станом і може бути порожнім уже після git add. Без підпису diff читається як "щось із чимось", і повторити порівняння не вийде.
Окремо звірте, що очікування тесту лишилося тим самим - 3. Якщо разом із кодом змінилося й очікуване число, це вже інша історія: перевірка підлаштувалася під поведінку, а не поведінка під вимогу.
Далі технічна дрібниця, на якій легко помилитися. Поки правку не закомічено, її видно в порівнянні робочого дерева з останнім комітом. Після коміту те саме порівняння покаже порожнечу, і це не означає, що в завданні нічого не змінювалося - просто зміна поїхала в історію, і порівнювати треба коміт із попереднім станом. Порожній diff сам по собі нічого не доводить, важливо, які два стани ви порівнюєте.
Що видно на скриншоті
Стан і дія
Кадр із числом 3 на табло підтверджує лише одне: у момент зйомки на табло було 3. Це не те саме, що "три збіги додали 3 очки". Між цими двома твердженнями лежить усе, чого в кадрі немає: з якого рахунку почали і що взагалі зробили.
Щоб кадр став свідченням, поруч доведеться записати сценарій. Небагато, чотири рядки:
- що відкрили: адресу сторінки або спосіб запуску, і яка це версія - з правкою чи без;
- початковий стан: на старті рахунок 0, старі дані не підтягнулися;
- дія: зібрали три збіги;
- спостереження: на табло 3, знято одразу після дії.
Без цього запису будь-який кадр можна отримати десятком способів. Відкрита ще вчора вкладка зі старою версією, інший запуск, рахунок, який уже був ненульовим, - усе це дасть картинку, яка має переконливий вигляд і не означає нічого.
Скриншота табло в цій статті немає навмисно. Скриншот для перевірки знімають після відтворення сценарію на потрібній версії, вручну або засобами автоматизації; намальоване чи зібране для ілюстрації табло свідченням не стає, навіть якщо збігається зі справжнім один в один. Коли робитимете свій кадр, знімайте табло цілком, вказуйте адресу сторінки в записі сценарію і зберігайте кадр поруч із цим записом - інакше вже наступного тижня не згадаєте, який це був запуск.
Що може прочитати модель
Картинку можна передати в сесію і попросити прочитати. Формулювання тут вирішує все: просіть назвати видиме число і перелічити сумніви ("чи видно початковий стан", "чи зрозуміло, яка це версія"), а не підтвердити заздалегідь заданий висновок. На прохання "підтверди, що баг виправлено" легко отримати ввічливу згоду, яка нічого не перевіряє.
Чи можна передати зображення, залежить від моделі та середовища, в якому ви працюєте. У Claude Code можна вказати шлях до збереженого зображення і попросити його прочитати. Якщо зображення не завантажилося, спершу перевірте шлях і доступність файлу; сама лише зміна моделі не гарантує, що проблема зникне.
Відповідь Claude Code про картинку - інтерпретація кадру, яку треба звірити із самим зображенням. Розбір зображення може помилитися в числі або домалювати деталь, якої там немає. І головне: з кадру не можна встановити, який рядок коду виправлено. Табло показує результат, а не причину.
Один сценарій до і після
Корисна пара має такий вигляд: та сама перевірка падає на зламаній реалізації і проходить на виправленій. Падіння показує, що перевірка взагалі помічає цей дефект, а проходження - що після правки дефекту в перевіреному сценарії немає.
Працює це за однієї умови: порівнюють однакові вхідні дані й однакові очікування. Той самий початковий рахунок, та сама кількість збігів, те саме очікуване значення 3. Ось зелений підсумок того самого тесту після правки:
✔ three matches give 3 points (1.3983ms)
ℹ tests 1
ℹ pass 1
ℹ fail 0
ℹ skipped 0Між прогонами змінюється реалізація, а тест, вхідні дані, очікування й умови запуску лишаються тими самими. Якщо довелося змінити вимогу або виправити очікування в тесті, отримайте нову пару прогонів із цією перевіркою: пояснення словами не замінює її запуску на обох станах. Мовчазне "було червоне, стало зелене" в такій ситуації вводить в оману.
І два файли з назвами before.txt та after.txt самі по собі нічого не гарантують. Назва файлу - не свідчення. Дивитися треба всередину, чи там справді одна команда, один тест, одне очікування. Контрольне повернення зламаного стану (той самий прийом із git stash) - окрема перевірка зі своїми правилами, тут досить знати, що червоне до правки береться зі справжнього прогону, а не з пам'яті.
Короткий EVIDENCE_LOG
EVIDENCE_LOG - у цій статті звичайний текстовий журнал із шести полів у такому порядку: СИМПТОМ, ЛОГ-ДОКАЗ, ПАДІННЯ НА ЗЛАМАНОМУ, ВИПРАВЛЕННЯ, ЧЕСНЕ ЗЕЛЕНЕ, СКРИНШОТ. Так зручніше зіставити симптом, виправлення і результат. Сам порядок полів не гарантує, що записи достовірні.
Усе, що ми збирали вище, розподіляється між цими полями. Команда й тека йдуть у поле про падіння, стани для порівняння - у виправлення, посилання на повні файли - туди, звідки вони взялися. Заводити поруч ще один пакет документів не потрібно.
Нижче навчальна схема заповнення: вона показує, що писати в кожному полі, а не звітує про виконані перевірки. У своєму журналі замініть текст фактичними результатами.
СИМПТОМ: у бонус-грі з початковим рахунком 0 три збіги
дають 30 очок замість 3. Повторюється щоразу: відкрити гру,
зібрати три збіги, подивитися на табло.
ЛОГ-ДОКАЗ: у виводі прогону "30 !== 3" в тесті
"three matches give 3 points", повний вивід у logs/test-fail.txt.
Окремо, з читання коду: у src/bonus-game/score.js
множник POINTS_PER_MATCH дорівнює 10. Це результат читання коду,
у виводі тесту числа 10 немає.
ПАДІННЯ НА ЗЛАМАНОМУ: HEAD a1b2c3d (навчальний ідентифікатор),
робоче дерево чисте; у коміті зламаний розрахунок і тест.
Тека - /project/bonus-game, команда - npm test.
У package.json scripts.test = node --test. Падає "three matches give 3 points",
причина "30 !== 3", tests 1, pass 0, fail 1, skipped 0, код виходу 1.
Фрагмент виводу вище, повний - logs/test-fail.txt.
ВИПРАВЛЕННЯ: POINTS_PER_MATCH змінено з 10 на 1 у файлі
src/bonus-game/score.js; інших змін немає. HEAD той самий a1b2c3d.
Diff: git diff HEAD, робоче дерево проти цього коміту;
збережено в diffs/score-fix.diff.
Очікуване значення в тесті лишилося тим самим - 3.
ЧЕСНЕ ЗЕЛЕНЕ: та сама команда npm test з тієї самої теки на коді
після описаної правки. Той самий тест проходить: tests 1, pass 1,
fail 0, skipped 0, код виходу 0.
Повний вивід - logs/test-pass.txt.
Сценарій із п'ятьма збігами не запускався.
СКРИНШОТ: screenshots/bonus-score-3.png. Гру відкрито заново
за адресою http://localhost:3000 з того самого робочого дерева
після правки. На старті рахунок 0, виконано три збіги,
на табло 3. Збереження результату в лідерборді не перевірялося.
Шляхи в прикладі - просто приклад. Повні логи, дифи й картинки кладуть туди, де в проєкті вже лежить щось подібне; окрема обов'язкова структура тек для цього не потрібна.
Зверніть увагу на два останні рядки полів 5 і 6. Пропуск позначають прямо, однією фразою: "не запускався", "не перевірялося". це не зізнання в лінощах, це межа висновку. Журнал без таких рядків здається повнішим, а насправді просто мовчить про те, чого ніхто не робив.
Перевірте себе
У завданні два критерії: розрахунок дає 3 очки за три збіги, коли рахунок починається з нуля, та інтерфейс після цих трьох збігів показує 3. На руках шість матеріалів:
- повідомлення агента "готово, баг виправлено";
- інструкція запустити
npm test; - фактичні прогони одного тесту: червоний до правки і зелений після;
- diff зі зміною множника;
- окремий кадр із числом 3, без опису запуску;
- запис відтвореного сценарію з прив'язаним до нього кадром.
Яких із них досить для двох критеріїв і що лишається неперевіреним? Прикиньте відповідь, перш ніж читати далі.
Розбір. Перший критерій закриває пункт 3: справжня пара прогонів на одному тесті. Diff із пункту 4 пояснює, що змінилося в коді, але прогону він не замінює - зміна і виконання це різні речі. Другий критерій закриває пункт 6: кадр разом із записом сценарію, де видно початковий стан і дію. Пункти 1 і 2 не підтверджують нічого: повідомлення про готовність не містить підтвердження, яке можна перевірити, а інструкція описує майбутню дію. Пункт 5 показує число 3 і на цьому зупиняється, нарахування за ним не встановити. Ну і збереження результату в лідерборді лишається неперевіреним навіть з усіма шістьма матеріалами на столі: сценарію, в якому збережене значення зчитали ще раз, серед них немає.
Зібрати такий журнал можна і в сесії. Готовий промпт:
Збери EVIDENCE_LOG за шістьма полями. Для кожного висновку вкажи
фактичну перевірку, стан коду і джерело результату.
Окремо познач, що не запускалося. На скриншоті назви тільки
те, що видно, і не роби з нього висновку про правильність внутрішнього розрахунку.Як зібрати докази з Claude Code
Порядок роботи виходить приблизно такий:
- агент пов'язує кожен критерій із конкретною перевіркою: що запустити, на якому стані коду, що вважати результатом;
- виконує ті перевірки, які в цьому середовищі доступні, і показує команду з оригінальним виводом;
- додає спостереження: фрагменти виводу, посилання на повні файли, опис відтвореного сценарію;
- явно позначає межу: що лишилося незапущеним, чого за наявними матеріалами стверджувати не можна.
За вами лишається перевірка самих свідчень: відкрити додані файли й подивитися, що там усередині, звірити сценарій із тим, який описано в критерії, і поставити одне незручне запитання про пункт, за яким перевірки не видно. Зазвичай цього вистачає, щоб відрізнити зібрані докази від акуратно оформленого переказу.
Обсяг файлів не замінює відсутньої перевірки. Десять вкладень, жодне з яких не запускало потрібну поведінку, доводять стільки ж, скільки й нуль вкладень. Краще три короткі записи, з яких видно команду, стан і результат.
Технічна довідка: git diff, git stash, Node.js test runner, npm test, зображення в Claude Code.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ