Як я поєднав React Native, AI та агентний SDLC під час розробки KindMorsel

💡 Усі статті, обговорення, новини про Mobile — в одному місці. Приєднуйтесь до Mobile спільноти!

Я — Ігор Маринич. Багато років працюю з мобільною розробкою на React Native та створюю власні продукти. Цей текст буде корисний розробникам, які вже експериментують з AI-агентами, але хочуть зрозуміти, як вписати їх у звичайний цикл створення мобільного застосунку: від продуктових вимог до перевірки на справжньому iPhone.

Ідея KindMorsel з’явилася з бажання переосмислити звичний підхід до застосунків про харчування. Багато з них зосереджені на калоріях, обмеженнях і тому, що слід «прибрати» з раціону. Мені хотілося, щоб людина спершу обирала те, що справді хоче з’їсти, а застосунок допомагав знайти просте доповнення до цієї їжі — без заборон і відчуття провини.

Останнім часом я багато працюю з AI-інструментами й хотів поєднати цей досвід із мобільною розробкою навколо зрозумілої щоденної задачі. Окремим поштовхом став RevenueCat Shipaton: він дав нагоду втілити цю ідею у власному мобільному продукті.

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

Одна невелика дія замість щоденника харчування

Основний сценарій починається зі звичайної їжі. Людина може описати її текстом, сфотографувати або записати голосом. Після розпізнавання вона бачить список інгредієнтів і може його виправити. Далі застосунок показує одну ідею доповнення, якщо в каталозі є перевірений сумісний варіант. Пропозицію можна прийняти або залишити їжу як є.

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

Екран KindMorsel з однією ідеєю доповнення та дією Leave as it is

Екран результату: людина бачить запропоноване доповнення і може не змінювати їжу. Скриншот із локального набору для версії 1.0.2.

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

Екран збережених страв KindMorsel

Збережені страви — приклад того, як знайомі варіанти повертаються у сценарій вибору. Скриншот із локального набору для версії 1.0.2.

Де в продукті працює AI, а де — звичайний код

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

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

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

Технічно мобільний клієнт написаний на Expo, React Native і TypeScript. Серверна частина використовує Python, FastAPI, PostgreSQL, SQLAlchemy й Alembic. Сервер відповідає також за квоти, доступ до даних та перевірку платного доступу; ці рішення не можна довіряти стану в мобільному клієнті. Окремі перевірки охоплюють доступ між акаунтами й транзакції PostgreSQL.

SDLC: як дати агенту задачу, яку можна прийняти

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

Цикл однієї задачі виглядає так: визначити обсяг і залежності, підготувати пакет контексту, реалізувати зміну в окремому Git worktree, запустити вузькі й загальні перевірки, отримати незалежне рев’ю та пройти gate. Для кожної перевірки зберігається відбиток вихідних файлів. Якщо після тестів змінився код, попереднє «усе зелене» вже не є доказом для нової версії: перевірки й рев’ю потрібно повторити.

Важлива деталь — один автор змін на один worktree. Це зменшує ризик, що дві паралельні сесії перезапишуть одна одній файли, а потім обидві звітуватимуть про нібито власний результат. Координатор керує залежностями й прийманням; виконавець пише код; рев’юер у новому контексті читає вимоги, diff і суміжні ділянки. Рев’юер не має просто підтвердити висновок виконавця.

Цей процес не замінює мого рішення про продукт. Критерії приймання, пріоритети та зміни обсягу залишаються явними. Так само успішне завершення процесу агента ще не означає, що функція працює на пристрої або готова до релізу.

Один показовий цикл: від роботи агента до регресійних тестів

Зручний приклад — рання задача KM-002, текстовий сценарій на тестових даних. Вона з’єднала кілька екранів: введення їжі, перевірку інгредієнтів, результат, підтвердження та необов’язковий відгук. На цьому етапі це була демонстрація переходів і стану UI, а не перевірка реальної моделі розпізнавання чи якості харчових рекомендацій.

Hermes Agent підготував план і реалізацію. Після цього перевірка виявила конкретні проблеми: відгук міг переноситися на змінений склад їжі; повторний вибір тієї самої відповіді про голод впливав на збережений стан; різні пробіли у введенні могли створювати дублікати. Додані регресійні тести спочатку відтворили проблеми — п’ять тестів падали. Після виправлення пройшли 17 мобільних тестів, загальна перевірка, незалежне рев’ю та gate для тієї самої версії коду.

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

Є й менш гладкий приклад: в іншій задачі стадія планування Hermes завершилася без плану через перерваний API-виклик. План довелося скласти координатору, після чого агент продовжив реалізацію. Це корисне нагадування: оркестрація має не лише запускати наступну стадію, а й зупинятися, коли попередня не дала потрібного артефакту.

Тут варто розвести дві назви. Hermes Agent у моєму процесі — інструмент оркестрації розробки. Hermes у React Native — JavaScript-рушій, з яким збирається iOS-застосунок. Вони мають однакове ім’я, але виконують зовсім різну роботу.

RAG для перевірки продуктових рішень

Ще одне застосування AI в процесі — RAG на основі власних нотаток із перевіреного джерела про харчування. Я не переносив текст першоджерела у застосунок і не будував чат, який цитує книгу користувачеві під час кожного прийому їжі. Пошук потрібен команді під час розробки: знайти короткі перевірені нотатки з посиланням на главу чи сторінку, повернутися до першоджерела і оцінити конкретний продуктовий сценарій.

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

Для сценаріїв роботи з їжею я використовую чотири рівні оцінки: повна відповідність перевіреному джерелу; часткова відповідність із прогалиною; питання, на яке джерело не дає відповіді; прямий конфлікт із перевіреним принципом. Прогалину потрібно виправити або дослідити окремо. Конфлікт зупиняє впровадження. Важливо, що технічні рішення на кшталт Apple Sign In чи зберігання даних не отримують штучного «обґрунтування книгою».

Найконкретніший наслідок цієї перевірки стосувався голоду та складу їжі. У ранніх правилах застосунок вимагав усі три харчові ролі для висновку, що страва «повна», а низький рівень голоду міг автоматично прибрати ідею доповнення. Після звірки стало зрозуміло, що така логіка перетворює гнучкий підхід на жорстку формулу. Правила переглянули: відповідь про голод можна пропустити; наявність двох ролей не створює обов’язку додати третю; людина може залишити їжу без змін. Водночас точні правила каталогу й конкретні поєднання я позначаю як гіпотези KindMorsel, які потребують власної перевірки.

Це, мабуть, найважливіше, що дав RAG у цьому проєкті. Він допоміг не «автоматизувати істину», а зробити видимою межу між джерелом, моєю інтерпретацією та тим, що ще невідомо.

Мобільна частина все одно перевіряється на iPhone

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

Коли я підключав фото й голос, нативна перевірка виявила зміну в Expo SDK 57: старий спосіб передавати файл у multipart-запиті через один URI більше не працював із типовим fetch. Клієнт почав передавати байти через Expo FileSystem, а регресійний тест перевірив реальний multipart-енкодер встановленого Expo. Моки мережевого запиту не дали б того самого доказу.

На фізичному iPhone окремо перевірялися запис голосу, камера, відмова в дозволах, скасування запису та відновлення після збою мережі. Один зі сценаріїв відкриття налаштувань отримав від iOS відмову. Застосунок після цього став показувати людині зрозумілий ручний шлях до потрібного системного розділу. Це маленька зміна, але саме вона перетворює тупик на наступну дію.

Інша історія — Dynamic Type. Один із TestFlight-білдів виглядав нормально зі звичайним розміром шрифту, проте після закриття екрана підписки на фізичному iPhone збільшений текст обрізав заголовок і підказки. Локальна правка в симуляторі не була достатнім доказом, що проблема зникла на пристрої. Такий білд я не міг назвати прийнятим лише через успішні Jest-тести чи збірку.

Екран базових страв у KindMorsel

Каталог базових страв. Для таких екранів я окремо перевіряю досяжність дій, прокручування й текст різного розміру. Скриншот із локального набору для версії 1.0.2.

До цього додається перевірка серверної частини. Загальний npm run check запускає статичні й unit-перевірки, але сам собою не доводить поведінку транзакцій PostgreSQL або застосування міграцій. Для них є окремі інтеграційні сценарії. І навпаки: backend-тести не доводять, що системний діалог покупки правильно працює на iPhone.

Що я залишив за людиною

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

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

Для KindMorsel поєднання mobile та AI виявилося не одним ефектним викликом моделі, а серією меж відповідальності. Модель розбирає вхід; користувач підтверджує склад; перевірені правила ухвалюють рішення; сервер контролює доступ і квоти; агент виконує обмежену інженерну задачу; рев’ю й перевірки показують, чи можна прийняти її результат. Найбільше користі я отримав саме тоді, коли ці межі були записані й перевірялися на конкретних прикладах.

KindMorsel уже доступний в App Store. Запрошую всіх охочих спробувати застосунок у повсякденному житті або протестувати його й поділитися відгуком у коментарях. Буду вдячний за зауваження щодо зручності, корисності запропонованих доповнень і помилок, які ви помітите. Ваш досвід допоможе визначити, що варто покращити далі.

👍ПодобаєтьсяСподобалось6
До обраногоВ обраному4
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter