Привет, Хабр. На связи Маша Лещинская, Head of QA в Surf. Мы все любим пет-проекты, и еще больше — пет-проекты на AI. Но есть нюанс: большинство таких штук забываются через неделю, потому что их сложно и дорого поддерживать. Я сделала проект, который живёт уже третий месяц, и причина не в каких-то крутых технологиях, а в том, что цена поддержки стала минимальной.
Рассказываю, как пришла идея и что из этого вышло. Больше инсайтов от меня и других руководителей разработки ищите в Телеграмм-канале «Директорат Surf обсуждает».
Сначала — предыстория
У нас в компании большой парк мобильных устройств – их регулярно берут QA. Когда людей и устройств становится много, все начинают путаться. Периодически нужны одни и те же модели, часть устройств уезжает домой к сотрудникам, часть лежит в офисе, у каких-то заканчивается срок возврата, а перед регрессией нужно понимать, что реально доступно.
Когда-то у нас была нормальная система бронирования: с интерфейсом, слотами и статусами. Потом она умерла. Не потому что была плохая, а потому что её нужно было поддерживать. Поддержка всегда означает чьё-то время, а во внутренних инструментах это время часто проигрывает более срочным задачам. В какой-то момент мы откатились к самому простому и честному способу координации — к чату.
Первая версия за вечер
Первую версию я собрала вечером. Стек выбрала намеренно лёгким: хотелось, чтобы в проекте не появилось ничего, что нужно регулярно обновлять, поддерживать или оплачивать только ради того, чтобы система продолжала жить:
-
Vanilla JavaScript — без фреймворков;
-
Firebase — Firestore, Hosting, Google OAuth;
-
PWA — чтобы система открывалась с телефона без установки.
Получилась реальная система: каталог устройств, бронирование в один клик, история, роли и базовые статусы. Я задеплоила её, скинула ссылку команде и честно думала, что люди немного поиграются и забудут.

Три месяца спустя: всё работает
Не забыли.
Команда продолжила пользоваться системой. Потом начали приходить запросы на фичи, всё чаще и чаще. Раньше, чтобы добавить фичу, разработчику нужно было выкроить вечер, потом ещё один, потом отложить из-за более срочных задач. Теперь это можно сделать в обеденный перерыв.
Моя система постепенно перестала быть просто внутренним инструментом и стала живым продуктом, на котором можно проверять AI-разработку в реальных условиях.
Продолжаем развивать проект
Покажу теперь, как это все работает и из чего состоит.
Каталог с умными фильтрами
В базовой версии каталог был обычным списком устройств с поиском и фильтрами по типу, ОС и статусу. Поиск работает с задержкой не больше 200 мс, чтобы интерфейс оставался быстрым и не раздражал пользователя.
Но самое интересное началось не с базовых фильтров, а с запросов команды. Например, появился запрос: «Хочу видеть только то, чем я ещё никогда не пользовалась». Так родился фильтр «Не используемые мной».
Система анализирует историю бронирований конкретного пользователя и показывает только устройства, по которым у него ещё нет записей. Это удобно для расширения покрытия.
Ещё полезное — автоопределение устройства. Если открыть систему с телефона, она определяет ОС и подсвечивает релевантные устройства. Это не меняет весь сценарий, но убирает маленькое трение, которое обычно раздражает в повседневной работе.
Бронирование с контекстом

Бронирование работает в двух режимах: в офисе и домой. Если устройство берут в офисе, достаточно указать кабинет. Если берут домой, добавляется дата возврата.
Есть разделение под проекты. Если у сотрудника несколько активных проектов, он указывает, под какой именно берёт девайс. Потом эта информация попадает в матрицу покрытия устройствами.
Когда пришёл запрос «устал возвращать по одному», я подключила кнопку «Вернуть все» на вкладке «Мои». Одно нажатие — и все активные устройства пользователя возвращаются. Система показывает тост с количеством, чтобы было понятно, что именно произошло.
Матрица покрытия
Самая сложная фича пришла из наших QA-процессов. Мы ведём матрицу покрытия устройствами, о которой писали здесь.
В системе появилась сущность «проект» с минимальными поддерживаемыми версиями ОС. Сотрудники привязаны к проектам, а история бронирований знает, под какой проект брали устройство.
В режиме «Матрица покрытия» выбираешь проект и видишь, какие устройства ещё не тестировались на нём, что давно не использовалось, топ самых частых.


Активность с устройствами
Отдельный раздел показывает аналитику по людям и устройствам с фильтром по периоду и графиками. Сначала это было просто полезно для прозрачности: кто какие устройства берёт, какие девайсы используются часто, а какие почти не трогают.
Потом вокруг этого появилась своеобразная геймификация. Рейтинг пользователей считается по количеству уникальных устройств, которые сотрудник брал за период. Именно уникальных, а не просто по количеству бронирований.

Рейтинг сотрудников и мотивация. Лидеру — поощрение, второму и третьему — догоняющие сообщения в духе «ещё немного, возьми устройство, которое давно не брал». Ребята действительно смотрят на рейтинг и иногда специально берут незнакомый девайс, чтобы подняться в списках.
Популярность устройств. На карточках каталога появились промо-плашки. Система подсвечивает самые востребованные устройства и те, что давно никто не брал.

Здесь получается двойной эффект. С одной стороны, это мотивирует брать разные устройства, а не ходить по одному и тому же привычному набору. С другой — это сигнал для закупок. Если устройство постоянно востребовано, возможно, таких моделей не хватает. Если девайс лежит мёртвым грузом, возможно, его не нужно докупать или стоит пересмотреть его роль в тестировании. Экономим и тут.
Подбор устройств
Отдельный режим для тех, кто ищет устройство по техническим характеристикам, а не по названию.
Можно фильтровать по разрешению экрана, соотношению сторон, например 20:9, и плотности пикселей — PPI. Есть переключатель «Только точное разрешение», если нужны устройства без допустимых отклонений.

Экспорт и отчёты
Данные можно выгрузить в нескольких разрезах из одного пространства в админке. Есть CSV-выгрузки: история бронирований, каталог устройств с выбором нужных колонок, статистика активности, ежемесячный отчёт, сломанные устройства, просроченные возвраты и проблемные ситуации.Есть PDF-отчёт — ежемесячная сводка по парку устройств: какие девайсы брались, кто и сколько пользовался, какая оборачиваемость. Такой отчёт удобно передать руководителю или использовать на ретроспективе по парку.
Аналитика и прогнозирование закупок
Это появилось само как побочный эффект нормального учёта.
Раздел «Анализ устройств» разбит на четыре вкладки: неиспользуемые устройства, которые не брали больше N дней; просроченные возвраты; оборачиваемость — сколько раз брали и среднее время использования; сломанные устройства.
Теперь можно смотреть, каких устройств не хватает и по каким платформам появляется очередь, что лежит мёртвым грузом и не нужно докупать, какие версии ОС недопредставлены в тестировании.
Это не полноценная BI-система, но для внутреннего инструмента такого уровня уже достаточно, чтобы принимать более осознанные решения.


Feature flags и версионирование
Экспериментальные фичи живут за feature flags в Firestore. Их можно включать и выключать из админки без редеплоя. Это удобно, когда нужно раскатить фичу постепенно, проверить её на небольшой группе или быстро отключить, если что-то пошло не так.
Есть механизм Force Update. Администратор задаёт минимальную версию приложения, а пользователи с устаревшей версией видят просьбу обновить страницу. Клик на версию открывает диалог с историей изменений.
Эта мелочь сильно упрощает взаимодействие с PWA-версиями: пользователи не остаются на старой версии, так как система вовремя обновляется.

Как работает конвейер
Спецификации как рельсы для AI
Это главное, что я поняла за три месяца: качество результата определяет не детальность промпта, а качество контекста, который AI получает автоматически.
Промпт вроде «добавь фильтр “Не используемые мной”» сам по себе слишком общий. Без контекста он может привести к чему угодно: лишней логике, странному UI, тестам не того поведения или изменениям не в тех местах.
|
Поэтому полный цикл выглядит так: 1. Сначала фиксируется, зачем нужна фича и что меняется, |

Где AI справился, а где облажался
С feature flags AI справился хорошо. Аккуратно реализовал хранение флагов в Firestore, переключение из админки без редеплоя и применение изменений без перезагрузки страницы.
Тестовая архитектура тоже получилась сильной. AI предложил связку Screenplay pattern + Page Object с небольшими подсказками, и дальше смог выдерживать её в последующих тестах. В проекте появилось 38 Screenplay-задач (TakeDevice, BookDeviceHome, ToggleFeature, …) плюс 15 Page Objects. AI предложил именно эту архитектуру и выдержал её во всех последующих тестах.
Граничные случаи в тестах стали отдельным плюсом. Мок Firebase с поддержкой мутаций позволяет воспроизводить состояния, которые сложно поймать вручную. Orphan device (устройство без владельца), одновременное бронирование двумя пользователями, ошибка записи в базу — это просто мутация конфига:
const overdueMyDeviceConfig = configWithMutations((config) => { const device = config.data.devices.find(d => d.id === 'dev-booked-home'); device.bookedUntil = { __ts: true, value: new Date(Date.now() - 24 60 60 * 1000).toISOString() };});
Где плохо
God Object вместо рефакторинга. Каждую новую фичу AI добавлял в devices.js. Через несколько недель файл вырос до 305 KB и содержал семь независимых доменов: каталог, бронирование, историю, матрицу покрытия, матчер, CRUD, аналитику. AI оптимизировал локально — видел файл, дописывал туда. Никто не смотрел на размер целиком. Пришлось в отдельной задаче просить явный рефакторинг.
setTimeout вместо Promise. В нескольких местах вместо нормального async/await появился setTimeout(fn, 100) — ждать, пока данные загрузятся. Это работает на хорошем соединении и ломается на плохом. AI видел timing issue и брал самый простой инструмент.
N+1 запросы в админке. Загрузить список пользователей → для каждого отдельным запросом загрузить назначения. 50 пользователей = 50 запросов к Firestore. Поймали только когда квота free-плана начала уходить быстрее ожидаемого.
Тест несуществующего поведения. При генерации тестов для матрицы покрытия AI написал тест, который проверял тултип с процентом покрытия при клике на устройство. Тултип в спеке упоминался как идея — не как реализованная фича. AI воспринял его как часть требований. Тест прошёл бы только если бы тултип существовал. Причина — не в промпте, а в неточной спеке: граница между «что есть» и «что хотелось бы» была размыта. Именно поэтому дельта-спека пишется до кода, а не после.
innerHTML без санитизации. Прямая вставка HTML-строк в DOM — паттерн, который AI воспроизводил стабильно. Для внутреннего корпоративного инструмента с авторизацией через Google это некритично, но это потенциальная XSS-уязвимость, которую нужно было явно запросить исправить.
Каждый промах — это апдейт фреймворка
Важный момент: мы не просто фиксировали найденные проблемы и шли дальше. Каждый повторяющийся паттерн превращался в изменение в sdlc-dev-framework: новый этап, правило code review или отдельный скилл. Например:
-
После истории с setTimeout вместо Promise в фреймворк добавился этап статического анализа async-кода.
-
После God Object появился явный шаг архитектурной декомпозиции перед реализацией.
-
После теста несуществующего поведения в шаблон дельта-спеки добавилось разделение «реализовано сейчас» и «идеи для будущего».
-
После N+1 запросов в code review чеклист вошёл пункт про пакетные запросы к Firestore.
Этим проект и ценен как полигон. AI все равно ошибается везде. Здесь же мы используем живой продукт и четко видим, где именно AI ошибается. И тогда можно улучшать и совершенствовать проект.
Чек-лист: страховка от AI-ошибок
Когда фича готова, прошу ИИ пройтись по единому чек-листу, который сделала для того, чтобы не терять важные изменения и поддерживать проект в актуальном состоянии. Каждый пункт в нём появился на основе наших отработок.
-
Спецификация — открыт proposal, созданы дельта-спеки, пройдена валидация спек.
-
Discovery-документация — обновлены бизнес-требования, use cases, E2E-флоу.
-
Данные и доступы — обновлены правила Firestore при новых коллекциях или ролях.
-
UI и логика — разметка, стили, JS-модули.
-
Feature flags — если постепенный rollout, добавлен флаг.
-
Ручные тесты — обновлены компонентные и сценарные тесты в JSON.
-
Автотесты — новый *.spec.ts, обновлены Page Objects, Screenplay-задачи, мок-данные.
-
Документация — обновлены README.md и DOCUMENTATION.md.
-
Версия — поднята в js/version.js, синхронизирована скриптом.
-
Финальные проверки — playwright test, smoke-check ключевых сценариев.
10 разделов, около 30 пунктов внутри. Большинство занимают минуты. Я терпеть не могу создавать процесс ради процесса, поэтому для меня такой чек-лист — страховка, которая позволяет AI генерировать код, а не мусор.
Что в итоге
-
Живой сервис, которым реально пользуется команда
-
23 фичи за три месяца
-
Время от идеи до MR — за обеденный перерыв
Больше о таких инсайтах, наших внутренних проектах, ускорении и автоматизации с помощью AI читайте из первых рук — от хедов в нашем ТГ-канале «Директорат Surf обсуждает».
ссылка на оригинал статьи https://habr.com/ru/articles/1038990/