Pet-проект · Anton N · 2026

AI-интервьюер собирает профиль за разговор. Затем выгружает PDF под каждую вакансию.

«Один профиль. Резюме под каждую позицию.» Подробный профиль заполняется один раз (разговором с AI-интервьюером или импортом), дальше под каждую вакансию AI собирает отдельный PDF с нужными акцентами.

обновлено 2026-06-21
01 — что это

Из чего состоит продукт

2 абзаца
продукт

DevMatch AI — приложение для подготовки профиля кандидата. Ядро ценности — профиль: он заполняется один раз и переиспользуется бесконечно — под каждую целевую роль AI генерирует отдельное PDF-резюме, сам расставляя акценты. Разговор с AI-интервьюером — механизм, который делает глубокое заполнение безболезненным.

доступ и данные

Авторизация и хранение резюме — через внешний сервис nefron-mic. У каждого пользователя один профиль; роли user/admin приходят с сервера.

02 — как работает

От разговора до PDF

11 блоков
01
Разговор
голос / текст
02
Извлечение
LLM · facts
03
Профиль
8 разделов
04
PDF под роль
ATS-friendly
aАвторизация и сессия
Вход — по логину и паролю через внешний сервис nefron-mic (метод auth.php). Пароль шифруется на сервере приложения алгоритмом AES-256-CBC и не хранится. В ответ приходит пользовательский токен и признак роли (обычный пользователь или администратор). Эти данные кладутся в подписанную httpOnly-cookie на 24 часа. Middleware проверяет сессию на каждой странице: без неё — редирект на /login. Регистрации и восстановления пароля нет — только вход.
bПрофиль пользователя
У каждого пользователя ровно один профиль (резюме). Он привязан к пользователю по сессии: какой профиль показывать и куда писать — сервер определяет сам из токена, клиент не может открыть чужой профиль. После входа резюме подтягивается с сервера nefron (getresume) и сравнивается с локальной копией: источником правды становится та версия, в которой больше заполненных полей (в норме они одинаковы — это защита от потери данных; если локальная богаче, она остаётся и целиком отправляется на сервер). Профиль хранится файлом на сервере приложения. Правки сохраняются сами: кнопки «Сохранить» нет — через короткую паузу после ввода поле автоматически сохраняется, а рядом с его заголовком коротко загорается отметка «Сохранено». Профиль можно держать открытым сразу в нескольких вкладках (побеждает последнее сохранение).
cAI-интервьюер (двухпроходный агент)
Диалог с кандидатом обрабатывают два прохода одной модели. Проход 1 (извлечение): из последних реплик модель вызывает инструменты записи и заполняет поля профиля — это единственное место, где данные пишутся в профиль. Идёт сверху вниз по карте приоритетов заполнения. Каждая запись проходит кодовую проверку (гард): значение не из справочника не записывается, выдуманный уровень навыка срезается — вместо тихой подмены ассистент честно переспрашивает. Система помнит, до какого места разговор уже разобран (курсор), — сбой не теряет факты, а просьба «запиши всё» проходит всю беседу. Проход 2 (разговор): только чтение — модель отвечает пользователю и подтверждает строго то, что реально записал первый проход, а незаписанное честно называет и уточняет. Есть голосовой ввод (через отдельный WS-relay к OpenAI Realtime, ключ не уходит в браузер).
dХранение переписок (чатов)
История чата хранится рядом с профилем, в отдельном файле <пользователь>.chat.json в формате { messages, costUsd }. Каждое сообщение — это { id, роль (user/assistant), текст, время, токены }. Токены проставляются на сообщении ассистента (расход за ход), накопленная стоимость диалога — на весь чат. Переписки лежат локально на сервере приложения, а не на сервере nefron.
eИмпорт резюме (PDF / DOCX → профиль)
Из файла извлекается текст И гиперссылки (в PDF ссылка «LinkedIn» живёт отдельным слоем — в контакты попадает реальный адрес, а не слово). Модель видит ПОЛНЫЙ текст резюме и ПОЛНЫЙ текущий профиль и за одну генерацию возвращает только то, что нужно заполнить или изменить. Применяет изменения код по правилам: объективные факты (имя, контакты, образование, компании/периоды) — резюме источник правды; списки (контакты, языки, навыки) объединяются поэлементно без потерь; описания сливаются в лучшую версию с фактами из обоих источников; целевые поля (роль/зарплата/формат) — только в пустые. Каждая запись проходит тот же кодовый гард, что и записи из чата. Перед импортом автоматически делается снимок профиля — на экране результата есть «Откатить импорт». Результат показывается честным отчётом (заполнено новых / обновлено / не записано и почему) с предупреждением, если имя в файле не совпадает с именем профиля. Прогресс в окне — настоящий, по разделам разбора.
fЭкспорт PDF под роль (умный отбор: оценка → отбор → составитель → рецензент)
Резюме не вываливает весь профиль, а собирает выжимку под выбранную роль. Сначала модель оценивает релевантность каждой карточки опыта, проекта и метода под эту роль. Затем код детерминированно отбирает, что войдёт, держа объём в рамках одной страницы: контента мало — берётся всё, много — только самое важное под роль; места работы при этом не выкидываются (пробелы в хронологии — плохой сигнал), сокращается глубина (число кейсов и проектов). По отобранному составитель собирает документ: навыки — 2–3 осмысленные группы под конкретную роль (без уровней владения); по каждому месту работы 3–5 конкретных тезисов плюс блок «Ключевые кейсы» с привязанными к этому месту проектами; шаблонные фразы («управлял полным циклом» без конкретики) запрещены; саммари опирается на авторское «О себе». Готовый черновик проходит через второго агента-рецензента, который вычищает шаблонность и всё, чего нет в профиле, и не имеет права урезать собранный опыт и кейсы (если рецензент упал — уходит черновик). Контакты и ссылки в резюме кликабельны: соцсети показываются названием платформы (Telegram, LinkedIn, GitHub), ссылки проектов — доменом, диплом — словом. Рендер в PDF (@react-pdf/renderer), шрифт Carlito — корректная кириллица и чистый текстовый слой для копипаста и ATS. Доступ к экспорту — не по абстрактному проценту, а по чек-листу минимума: имя, целевая роль, одно место работы (компания + должность), навыки. Пока минимум не набран, кнопка показывает прогресс («PDF · 46%»), а поповер — конкретный список недостающего с кнопками «спросить в чате». После минимума экспорт разрешён (черновое резюме — само по себе мотиватор дозаполнить), с порога «Хорошее резюме» — полный режим.
gСинхронизация резюме с сервером
Каждое изменение — руками или через AI — мгновенно сохраняется локально, а на сервер nefron (saveresume) резюме уходит ЦЕЛИКОМ с разумным гэпом: через 5 секунд после последнего изменения, но не позже 15 секунд с первой несинхронизированной правки (непрерывный поток правок не откладывает отправку бесконечно). Так сервер не бомбардируется запросом на каждый символ. При сбое данные не теряются — отправка повторяется автоматически, а в шапке появляется «сервер недоступен · повторяем». Вместе с резюме едет накопленная стоимость всех AI-запросов пользователя — в поле overview.cost (число); при входе она подтягивается обратно, чтобы счётчик продолжался. Серверный баг с пустыми списками устранён — проверено вживую (пустой список сохраняется без падения, стоимость записывается и читается).
hРоли и админ-функции
Роль (обычный пользователь / администратор) приходит с сервера при входе. Администраторам доступны: настройки, накопленная стоимость запросов (бейдж в нижнем баре + сумма в шапке чата) и выгрузки (все чаты в CSV, все профили в JSON). Стоимость — приватная метрика: обычным пользователям она не видна вообще, и сервер дополнительно проверяет права — скрытием в интерфейсе защита не ограничивается. Отдельная страница «Пользователи» (только для админов, пункт в меню-аватаре): список всех зарегистрированных людей с фото, именем и должностью, с поиском, сортировками (по активности чата, заполнению, имени и др.) и фильтрами (роль, наличие переписки). По выбору человека — три вкладки: «Профиль» (весь профиль целиком, только чтение: все разделы, поля и карточки, аккордеоном), «Резюме» (резюме под каждую целевую роль — уже сгенерированные скачиваются мгновенно, остальные генерируются по кнопке; видно, что сохранено, а что будет собрано ИИ) и «Чат» (полная история переписки с AI-интервьюером, с кнопкой скачать в JSON). Страница только для просмотра: профиль/чат не редактируются; резюме можно сгенерировать и скачать.
iОнбординг и обучающий тур (короче до продукта)
При первом входе пользователь видит два знакомящих экрана подряд, оба сокращены до минимума (~60–90 секунд + ~30 секунд). Кинопоказ-онбординг — 3 сцены в порядке иерархии ценности: «один профиль → резюме под любую роль» (зачем), «просто общайся» (как), и финальное мини-интервью «попробуй сам», где пользователь называет имя, роль и опыт — эти ответы сразу сохраняются в реальный профиль. Затем обучающий тур из 4 шагов (разделы, чат с упоминанием голоса, экспорт с честным текстом про минимум, автосохранение) — на десктопе; на телефоне после онбординга сразу редактор. Интервью в чате стартует только ПОСЛЕ онбординга и записи собранного — агент продолжает с четвёртого вопроса, а не здоровается заново. Если профиль почти пуст, вместо автостарта чат один раз предлагает развилку: «есть старое резюме? загрузить PDF/DOCX — или просто начнём разговор». Каждый экран показывается ровно один раз; в настройках есть кнопка «Пройти знакомство заново».
jВзвешенный прогресс, стадии и «Следующий шаг»
Процент заполнения считается по весам важности полей (та же карта приоритетов, по которой идёт интервьюер): название компании двигает прогресс сильнее, чем ссылка на диплом, — первые содержательные ответы дают видимый рост. Поверх процента — три именованные стадии: «Минимум для резюме» (~40%, открывает экспорт), «Хорошее резюме» (~65%) и «Сильное резюме» (~85%, зелёное кольцо на кнопке PDF); пересечение стадии отмечается тостом. В сайдбаре под прогресс-баром живёт виджет «Дальше»: несколько вопросов-фраз на выбор, что заполнить следующим — пользователь сам решает, в какую сторону вести разговор. Клик открывает раздел и направляет вопрос ассистенту, причём сообщения от лица пользователя в чате не показывается — выглядит, будто ассистент сам спросил. На телефоне — строкой над рельсой разделов.
kEvent-лог для фокус-группы
Минимальная продуктовая телеметрия без внешних SDK: события воронки (вход, онбординг пройден/пропущен, тур, первое сообщение, импорт, чекпоинты заполненности, клик по закрытому экспорту, скачивание PDF с ролью и стадией, длительность сессии) пишутся в файл рядом с профилем пользователя. Администратор выгружает весь лог одной кнопкой в меню-аватаре — по нему считается воронка «вошёл → первое сообщение → минимум → скачал PDF».
03 — статус

Что готово, что ограничено

обновлено 2026-06-21
готовоГотово
  • Импорт резюме v2: резюме — источник правды, ссылки из PDF, отчёт и откат

    Политика слияния от продакт-менеджера, по классам полей: объективные факты (имя, контакты, образование, компании/периоды) перезаписываются из резюме; списки (контакты/языки/навыки) объединяются поэлементно — телефон из резюме заменит старый, но Telegram из профиля не потеряется; описания (о себе, обязанности, проекты) сливаются в лучшую версию без потери цифр и конкретики; цели (роль/зарплата/формат) — только в пустые. Починен реальный баг: гиперссылки из PDF (слой аннотаций) и DOCX теперь извлекаются — контакт «LinkedIn» получает настоящий URL, а не слово. Модель видит полные тексты (раньше профиль показывался обрезанными превью — слепой мердж терял длинные формулировки) и возвращает только изменяемое. Перед импортом — автоматический снимок профиля с кнопкой «Откатить импорт»; после — честный отчёт (новых/обновлено/не записано) и предупреждение при несовпадении имени. Прогресс в окне настоящий — по разделам разбора. Повторный импорт того же файла даёт «ничего нового» — профиль не дёргается. Проверено живым прогоном на реальных PDF.

  • Надёжная запись фактов ассистентом: гард, докрытие пропусков, честный переспрос

    По разбору реальной сессии фокус-группы (test5): ассистент терял часть сказанного (обязанности не записались), молча подменял значение («вахта» превратилась в «Офис» — в справочнике формата нет вахты), выдумывал уровень навыка и говорил «записал», когда записал не всё. Теперь каждая запись проходит кодовую проверку: значение не из справочника физически не записывается — ассистент честно говорит «такого варианта нет» и переспрашивает (само пожелание сохраняется в «Ожидания»); уровень навыка пишется только если пользователь его реально называл. Пропуски перестали быть вечными: система помнит, до какого места разговор уже разобран, и после любого сбоя дочитывает с того же места; незаписанное превращается в явный «долг», который ассистент сам переспрашивает. Просьба «запиши всё, о чём мы говорили» теперь реально проходит всю беседу и дописывает только пустые поля (ручные правки не перетираются). Каждый ход пишет в журнал «что сказано vs что записано» — потери видны, а не предполагаются. Проверено живым реплеем той самой сессии test5: все потерянные тогда факты записываются, ложных значений нет.

  • Навыки и языки — компактные теги в строку

    Вместо строки-инпута на каждый навык — компактные чипы «название · уровень» (10–15 навыков занимают 2–3 строки вместо 15). Клик по чипу — поповер редактирования (переименовать, сменить уровень, удалить), «+ Добавить» в шапке поля — поповер добавления (достаточно названия, уровень — по желанию). Записи AI-интервьюера подсвечивают чипы той же хореографией и появляются с анимацией.

  • Выкатано в прод (весь nefron-стек, проверено вживую)

  • Реальная авторизация через nefron (AES-256-CBC)

  • Профили на пользователя + гидрация резюме при логине

  • Роли user/admin

  • Синхронизация всего резюме + стоимость на сервер — проверено вживую

    Резюме целиком (все секции: контакты, роли, навыки, опыт, проекты, образование, ожидания + накопленная стоимость в overview.cost) отправляется на сервер пакетом с гэпом (5с после последнего изменения, ретраи при сбое) и подтягивается обратно при входе. Проверено на проде: полный round-trip без потерь. Пол кодируется в 1 символ под серверную колонку.

  • Накопленная стоимость запросов — только админу (бейдж в баре + сумма в чате)

  • Экспорт всех чатов в CSV (только админ)

  • Трекинг токенов по сообщениям

  • Кинопоказ-онбординг (заполняет профиль из ответов) + обучающий тур (по разу, галочки в настройках)

  • Автосохранение полей без кнопки «Сохранить» + отметка «Сохранено» у поля

  • Единый формат дат (ДД.ММ.ГГГГ в UI, ISO на сервер) + аккуратный выбор в календаре

  • Загрузка резюме и экспорт PDF вынесены в шапку

  • Редактирование профиля в нескольких вкладках (блокировка убрана, last-write-wins)

  • Карточки категорий показывают полный текст (перенос, без обрезки)

  • Публичный лендинг на «/» для гостей + обогащённая страница входа

    Незалогиненный гость на «/» видит лендинг (демо «разговор → поля заполняются», «один профиль → резюме под роль», призыв попробовать); залогиненный — сразу редактор. Страница входа: фактура, ценности, показ/скрытие пароля. Навигация между «/», /about и /login замкнута в обе стороны.

  • Полноценная мобильная версия редактора

    На экранах уже 1024px редактор перестраивается: вместо сайдбара — горизонтальная рельса разделов с кольцами прогресса, чат с AI-интервьюером открывается снизу выезжающим листом по кнопке в нижнем баре. Пока агент пишет в профиль, лист сам сжимается в полоску — «магия» заполнения полей видна и на телефоне. Лендинг, вход, /about и онбординг тоже адаптированы; раскладка на 390px проверяется автоматически (layout-чекер).

  • Плавная анимация записи агентом (без «дёрганья»)

    Подсветка раздела и поля при записи AI теперь включается и гаснет плавно (мягкий вход свечения, эластичные переходы между фазами), смена раздела — спокойный кроссфейд, автоподстройка высоты текстовых полей больше не «резинит» при печати.

  • Синхронизация: локально сразу, на сервер — с гэпом, при входе побеждает полная версия

    Каждая правка мгновенно сохраняется локально (в шапке — «сохранено»), а на сервер nefron резюме уходит целиком пакетом: через 5 секунд после последнего изменения, максимум через 15 секунд непрерывной активности — сервер не бомбардируется запросом на каждое поле. Если отправка падает, в шапке появляется «сервер недоступен · повторяем» и отправка ретраится до успеха; ошибки логируются. При входе локальная и серверная версии сравниваются по количеству заполненных полей — источником правды становится более полная (в норме они одинаковы; это защита от потери данных: если сервер отдал огрызок, локальная копия не затирается, а отправляется на сервер). Версии резюме хранит сервер — локальных бэкапов нет. Корректность закреплена тестами (пустой, частичный, полный профиль, мусорные значения, потолок отправки) и живым round-trip на реальном сервере.

  • Фото профиля: загрузка, круговой кроп, локальное хранение

    В «Общих сведениях» вместо текстовой ссылки на фото — настоящая загрузка: кликом или перетаскиванием файла (JPEG/PNG/WebP). Фото ужимается до 1280px по длинной стороне ещё в браузере, затем пользователь выбирает в круге нужную область (двигает и приближает). На сервере приложения хранится необрезанный оригинал под уникальным именем (UUID), привязанный к пользователю; в интерфейсе показывается выбранный круг. Область круга можно поменять в любой момент без повторной загрузки файла. На сервер nefron фото не отправляется.

  • Компактные карточки полей: два состояния и поля по два в ряд

    Короткие поля (пол, дата рождения, город, гражданство, уровень, зарплата и т.п.) больше не растягиваются на всю ширину карточки — они идут парами в ряд. Карточки разделов с несколькими записями (места работы, проекты, образование) получили два состояния: свёрнутая — одна строка со сводкой (например, «Компания · Должность» и счётчик заполненности) без полей ввода, развёрнутая — привычные поля. Заполненные карточки по умолчанию свёрнуты (три места работы — три строки вместо трёх экранов), новые пустые открыты, а когда AI пишет в свёрнутую карточку — она раскрывается сама, чтобы запись была видна.

  • Связи между карточками — настоящий пикер

    Поле «Кейсы» в «Рабочем опыте» и «Методах и инструментах» теперь привязывает существующие карточки раздела «Проекты и кейсы» через выпадающий список с галочками (раньше было текстовое поле с подсказкой, которая на телефонах не работала). Ссылка на переименованную/удалённую карточку подсвечивается жёлтым. На сервер связи уходят прежним форматом — списком названий.

  • Новое позиционирование: «Один профиль. Резюме под каждую позицию.»

    По плану продакт-менеджера (демо для фокус-группы): hero лендинга продаёт актив (профиль) и результат (резюме под позицию), а не механизм («поговори с AI»); секция «1 профиль → 3 резюме» поднята сразу под hero с болевым заголовком «Хватит переписывать резюме под каждую вакансию» и контр-аргументом к «а я просто попрошу ChatGPT»; тексты STATS, карточки «Под вакансию» и финального CTA переписаны честно; кикер логина повторяет слоган.

  • Гейт экспорта: чек-лист вместо «заполните на 80%»

    Вместо абстрактного процента — конкретный минимум: имя, целевая роль, место работы (компания + должность), навыки. Закрытая кнопка показывает прогресс («PDF · 46%»), поповер — чек-лист недостающего, каждый пункт кликабелен («спросить в чате» — открывает раздел и кидает вопрос агенту). После минимума экспорт разрешён с честной подсказкой, что добавить; с «Хорошего резюме» — полный режим.

  • Взвешенная полнота + стадии + виджет «Следующий шаг»

    Процент — по весам fill-priority (важные поля двигают сильнее), стадии «Минимум/Хорошее/Сильное» с тостами на пересечении, в сайдбаре и на мобильной рельсе — одна детерминированная подсказка «Дальше: …» с кнопкой «спросить в чате».

  • Онбординг 5→3 сцены, тур 7→4 шага, развилка «импорт или разговор»

    Кино сокращено до «результат → общайся → попробуй сам» (~90 секунд), тур — до 4 шагов с честным текстом про экспорт. Починена гонка: интервью стартует только после записи собранного онбордингом (агент не переспрашивает имя/роль). Пустому профилю чат один раз предлагает загрузить старое резюме вместо разговора — самый быстрый путь к ценности.

  • Экспорт резюме v2: умный отбор под роль (оценка → отбор → составитель → рецензент)

    Раньше экспорт собирал резюме из всего профиля; теперь — выжимка под выбранную роль. Модель оценивает релевантность каждой карточки (опыт/проект/метод) под роль, дальше код детерминированно отбирает контент под объём одной страницы: мало — всё, много — топ под роль (места работы остаются для хронологии, режется глубина); сбой оценки → безопасный фоллбэк «взять всё». Навыки выводятся 2–3 смысловыми группами под конкретную роль без уровней; опыт — 3–5 тезисов + блок «Ключевые кейсы» с проектами, привязанными к этому месту работы (непривязанные идут отдельной секцией «Проекты»); методы вливаются в навыки и достижения. Агент-рецензент полирует и не может урезать число мест опыта и кейсов. Контакты и ссылки кликабельны (соцсети — названием платформы, проекты — доменом, диплом — словом), заголовки секций русские, фото в PDF пока нет. Чистая логика отбора и нормализации ссылок — на тестах; сквозной эвал на реальном профиле даёт 9 из 9 инвариантов полноты. Заложен фундамент под будущую фичу «резюме под конкретную вакансию».

  • Event-лог воронки (для фокус-группы) + админ-выгрузка

    События login / onboarding / tour / first_message / import / fill_percent-чекпоинты / export_locked_click / export_done / session_end пишутся в сайдкар рядом с профилем; админ скачивает общий JSON одной кнопкой. Внешних аналитик-SDK нет.

ограничениеОграничения на стороне сервера nefron
  • HTTPS: истёкший TLS-сертификат

    TLS-сертификат nefron-mic истёк (+ не загружен pdo_mysql) — работаем по http (server-to-server, на работу приложения не влияет). Нужен новый сертификат на стороне nefron.

  • saveresume падает целиком из-за одного «неподходящего» поля (robustness)

    Если поле не лезет в колонку БД, весь запрос падает PHP-фаталом и не сохраняется ничего. Наши известные триггеры устранены (пустой массив — пофикшен на сервере; gender — кодируем в 1 символ у нас). Остаётся пожелание серверу: не ронять весь save из-за одного поля. Отчёт: docs/nefron-save-robustness-report.md.

30
пунктов готово
8
разделов профиля
2
ограничения сервера
2026-06-21
обновлено