# Як перевіряти код від AI: чекліст перед комітом

> Практичний чекліст перевірки AI-згенерованого коду: типові помилки моделей, безпека, вигадані залежності, відповідність кодовій базі й тести як контракт. Із готовим markdown-чеклістом.

- Автор: Юра Скиба (https://cookiesoftware.io)
- Опубліковано: 2026-09-24
- Категорія: AI в роботі розробника
- Canonical: https://cookiesoftware.io/blog/ai-kod-chek-list-perevirky

---

**Коротка відповідь.** Код від AI перевіряється так само, як pull request джуна: уважно, за списком і без довіри до впевненого тону. Різниця в акцентах – моделі роблять специфічні помилки: пропускають edge cases, вигадують API, тягнуть застарілі патерни й повторюють небезпечні приклади зі свого навчання. Нижче – чекліст із поясненнями і готовий markdown-варіант для копіювання у свій процес.

## Чому це не паранойя

Згенерований код має підступну властивість: він завжди **виглядає** завершеним. Акуратні назви, коментарі, впевнена структура. Людський недописаний код видно одразу; недописаний AI-код виглядає як готовий. Тому перевірка за списком тут важливіша, ніж для власного коду, де ти хоча б пам'ятаєш, що зрізав кути.

## 1. Коректність: edge cases, які моделі люблять пропускати

Happy path майже завжди правильний. Перевіряй краї:

- **Порожні значення:** `[]`, `''`, `null`, `undefined`, `0`. Класика:

```ts
// Згенеровано: працює, поки items не порожній
function averagePrice(items: Product[]): number {
  const total = items.reduce((sum, item) => sum + item.price, 0);
  return total / items.length; // [] → 0/0 → NaN, тихо попливе далі по коду
}
```

  `NaN` не кидає помилку – він мандрує обчисленнями і випливає десь в UI як «₴NaN». Модель цей випадок пропускає стабільно.

- **Межі діапазонів:** перший/останній елемент, off-by-one в індексах і слайсах.
- **Асинхронні краї:** що буде, якщо запит впаде? Якщо два запити завершаться не в тому порядку? Якщо компонент розмонтується до відповіді?
- **Дублікати й повтори:** повторний клік, повторний виклик, той самий id двічі.

Прийом: спитай модель «які edge cases цей код не обробляє?» – вона часто чесно перелічить власні пропуски. Потім перевір сам, бо перелік теж буває неповний.

## 2. Безпека: модель вчилась і на поганих прикладах

- **Ін'єкції.** Конкатенація рядків у SQL, `dangerouslySetInnerHTML` з даними користувача, `eval`. Якщо дані користувача склеюються з кодом чи запитом без параметризації/екранування – стоп.
- **Секрети в коді.** Ключі й токени, вписані literal-ом «для прикладу». Всі секрети – лише зі змінних середовища.
- **Вигадані залежності.** Модель може імпортувати пакет, якого не існує, або з назвою, схожою на популярний (а зловмисники реєструють такі назви – це називається typosquatting). Правило: **кожен новий пакет із згенерованого коду перевіряй руками** на npm – хто автор, скільки завантажень, коли оновлювався.
- **Надмірні права й довіра до вводу.** Валідація на клієнті без валідації на сервері, відсутність перевірки власника ресурсу.

## 3. Відповідність кодовій базі

Модель без контексту пише «середньостатистичний» код, а не твій:

- **Дублювання утиліт.** Згенерований `formatDate` при живому `lib/dates.ts` – класика. Перед комітом: чи не існує вже функція/компонент для цього?
- **Стиль і конвенції.** Іменування, структура папок, підхід до стилів. Чужорідний шматок ускладнить життя всім наступним читачам.
- **Патерни актуальної версії.** Класові компоненти замість хуків, застарілі API бібліотек. Звіряй із документацією поточної версії, а не з упевненістю моделі.

Агентні інструменти, які бачать репозиторій, помиляються тут рідше – про це в [розборі агентного workflow](/blog/claude-code-dlia-react).

## 4. Тести як контракт

Найнадійніший спосіб перевірити згенерований код – тест, який ти написав або хоча б уважно прочитав **сам**:

- тест фіксує очікувану поведінку до того, як ти повірив реалізації;
- згенеровані тести читай прискіпливіше, ніж код: модель схильна писати тести, які проходять, а не тести, які перевіряють;
- один тест на головний edge case (порожній ввід, помилка запиту) цінніший за п'ять тестів happy path.

## 5. Приватні дані й ліцензії в промптах

Перевірка працює в обидва боки – дивись не лише на те, що виходить, а й на те, що ти відправляєш:

- не встав в промпт секрети, персональні дані користувачів, приватний код, який заборонено виносити (NDA);
- для робочих проєктів з'ясуй політику компанії щодо AI-інструментів до того, як вставив туди половину репозиторію.

## Приклад: та сама помилка до і після перевірки

Ін'єкція – найдорожча з типових помилок, тому окремо. Згенерований варіант, який «працює»:

```ts
// ❌ Дані користувача склеєні із запитом – SQL-ін'єкція
async function findUser(email: string) {
  return db.query(`SELECT * FROM users WHERE email = '${email}'`);
}
```

Введи в поле `' OR '1'='1` – і запит поверне всіх користувачів. Виправлення завжди одне – параметризація:

```ts
// ✅ Дані передаються окремо від коду запиту
async function findUser(email: string) {
  return db.query('SELECT * FROM users WHERE email = $1', [email]);
}
```

Модель знає правильний варіант і згенерує його, якщо попросити. Проблема в тому, що вона згенерує і неправильний – із тією ж упевненістю. Тому пункт чекліста, а не сподівання.

## Як вбудувати чекліст у процес

Чекліст, який лежить у нотатках, не працює. Що працює:

- **PR-темплейт.** Додай пункти в шаблон pull request – тоді перевірка відбувається там, де ти й так дивишся diff.
- **Питання моделі наприкінці генерації.** Стандартне завершальне повідомлення: «пройдись по цьому коду за чеклістом: edge cases, безпека, дублювання з кодовою базою». Модель – непоганий перший фільтр власних помилок; ти – другий і вирішальний.
- **Правило двох читань.** Перше читання – «що цей код робить», друге – «як його зламати». Друге читання і є рев'ю; без нього перше – просто ознайомлення.

## Готовий чекліст для копіювання

```markdown
## AI-код: перевірка перед комітом
- [ ] Порожні значення: [], '', null, undefined, 0 – поведінка визначена
- [ ] Межі: перший/останній елемент, off-by-one
- [ ] Асинхронність: помилка запиту, гонки, розмонтування
- [ ] Немає конкатенації даних користувача в SQL/HTML/команди
- [ ] Немає секретів у коді – лише env
- [ ] Кожен новий пакет перевірено на npm (автор, завантаження, свіжість)
- [ ] Не дублює наявні утиліти/компоненти проєкту
- [ ] Відповідає конвенціям кодової бази
- [ ] API звірено з документацією поточної версії
- [ ] Є тест на головний edge case, і я його прочитав
- [ ] У промпт не потрапили секрети/приватні дані
- [ ] Я можу пояснити кожен рядок цього коду
```

## Останній пункт – найважливіший

«Можу пояснити кожен рядок» – це фільтр, який ловить усе, що пропустили попередні. Якщо рядок незрозумілий, у тебе два чесні варіанти: розібратися або викинути. Третього – «закомітити і сподіватися» – у професійній роботі немає. Ширший контекст, де AI допомагає, а де заважає, – у базовій статті [AI для програміста](/blog/ai-dlia-prohramista); а системно ставити навичку читання чужого коду найшвидше через [регулярні code review з ментором](/blog/code-review-z-mentorom).
