惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Last Watchdog
The Last Watchdog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Secure Thoughts
MongoDB | Blog
MongoDB | Blog
博客园 - Franky
T
Tor Project blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Google DeepMind News
Google DeepMind News
L
LINUX DO - 最新话题
博客园_首页
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Vercel News
Vercel News
Last Week in AI
Last Week in AI
月光博客
月光博客
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Proofpoint News Feed
博客园 - 叶小钗
NISL@THU
NISL@THU
C
Check Point Blog
K
Kaspersky official blog
N
News and Events Feed by Topic
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
Arctic Wolf
T
Threatpost
GbyAI
GbyAI
L
LINUX DO - 热门话题
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy & Cybersecurity Law Blog
N
News and Events Feed by Topic
Scott Helme
Scott Helme
P
Privacy International News Feed
The Register - Security
The Register - Security
G
GRAHAM CLULEY
Recorded Future
Recorded Future
Apple Machine Learning Research
Apple Machine Learning Research
C
Cybersecurity and Infrastructure Security Agency CISA
B
Blog
Project Zero
Project Zero
Cyberwarzone
Cyberwarzone
Webroot Blog
Webroot Blog
Microsoft Security Blog
Microsoft Security Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
D
DataBreaches.Net
J
Java Code Geeks
AWS News Blog
AWS News Blog
Help Net Security
Help Net Security
Engineering at Meta
Engineering at Meta
M
MIT News - Artificial intelligence
T
Threat Research - Cisco Blogs
Google DeepMind News
Google DeepMind News

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Пет-проект, который не умер: система бронирования устройств как полигон для AI-разработки
Surf_Studio · 2026-05-25 · via Все публикации подряд на Хабре

Уровень сложностиПростой

Время на прочтение8 мин

Охват и читатели7.7K

Привет, Хабр. На связи Маша Лещинская, 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. Сначала фиксируется, зачем нужна фича и что меняется,
2. Затем строится дельта-спека с требованиями и сценариями,
3. Потом пишутся RED-тесты до кода,
4. После этого идёт реализация,
5. Затем code review
6. И только потом MR.

Где 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-ошибок

Когда фича готова, прошу ИИ пройтись по единому чек-листу, который сделала для того, чтобы не терять важные изменения и поддерживать проект в актуальном состоянии. Каждый пункт в нём появился на основе наших отработок. 

  1. Спецификация — открыт proposal, созданы дельта-спеки, пройдена валидация спек.

  2. Discovery-документация — обновлены бизнес-требования, use cases, E2E-флоу.

  3. Данные и доступы — обновлены правила Firestore при новых коллекциях или ролях.

  4. UI и логика — разметка, стили, JS-модули.

  5. Feature flags — если постепенный rollout, добавлен флаг.

  6. Ручные тесты — обновлены компонентные и сценарные тесты в JSON.

  7. Автотесты — новый *.spec.ts, обновлены Page Objects, Screenplay-задачи, мок-данные.

  8. Документация — обновлены README.md и DOCUMENTATION.md.

  9. Версия — поднята в js/version.js, синхронизирована скриптом.

  10. Финальные проверки — playwright test, smoke-check ключевых сценариев.

10 разделов, около 30 пунктов внутри. Большинство занимают минуты. Я терпеть не могу создавать процесс ради процесса, поэтому для меня такой чек-лист — страховка, которая позволяет AI генерировать код, а не мусор.

Что в итоге

  • Живой сервис, которым реально пользуется команда

  • 23 фичи за три месяца

  • Время от идеи до MR — за обеденный перерыв

Больше о таких инсайтах, наших внутренних проектах, ускорении и автоматизации с помощью AI читайте из первых рук — от хедов в нашем ТГ-канале «Директорат Surf обсуждает».