Российские технологии и цифровая экономика
ПоискRSS

Resume2human после habr: контакты в git, ошибки скоринга и развитие проекта

5 минут чтения

Неделя после Habr: как Git раскрыл рабочие контакты, а скоринг начал раздавать баллы бесплатно

Шесть дней назад я рассказывал о resume2human - приложении, которое превращает резюме в подборку подходящих вакансий, а затем для каждой позиции ищет одного-трёх реальных людей с указанием имени, должности и способа связи. За первую неделю после публикации в проект вошёл 21 коммит, появились девять pull request, а количество тестов выросло с 345 до 746.

При этом примерно половина первоначальных обещаний уже потеряла актуальность. Не потому, что проект пошёл не по плану, а потому что реальное использование быстро показало: поиск вакансий - только первая часть задачи. Найти подходящую позицию можно за полчаса, но ещё столько же уйдёт на поиск конкретного инженера, нанимающего менеджера или рекрутера. Именно здесь ручной процесс перестаёт масштабироваться.

resume2human - Windows-приложение, которое анализирует резюме, обходит 24 коллектора, включая ATS-доски 111 компаний, региональные сайты, LinkedIn, Telegram, Threads и обычный веб-поиск. Затем программа рассчитывает объяснимое совпадение между опытом кандидата и требованиями вакансии и предлагает до трёх людей, связанных с наймом. Автоматической рассылки нет: письмо пользователь составляет и отправляет самостоятельно.

Подробное описание обновлений и технических решений опубликовано в материале о развитии resume2human. Там же разобраны новые ограничения, ошибки и изменения в логике продукта: анализ резюме и поиск прямых контактов теперь рассматриваются как единый процесс, а не как две независимые функции.

Контакты нашлись внутри Git

Самым неожиданным открытием стала бесплатная ступень поиска контактов. Сначала казалось, что для неё понадобятся коммерческие базы вроде ContactOut, Lusha, Apollo или RocketReach. Однако у инженеров уже есть собственный открытый след - Git.

Каждый коммит содержит поле `author.email`. Оно обязательно, и даже если пользователь сегодня скрыл электронную почту в настройках GitHub или включил адрес формата `noreply`, старые коммиты могли быть опубликованы с настоящим адресом. В результате история репозитория превращается в своеобразную открытую базу инженерных контактов, хотя большинство разработчиков никогда не воспринимало её именно так.

Это не генерация адреса по шаблону и не догадка о корпоративной почте. Программа находит контакт, который когда-то был указан самим автором в публичном коммите. Новый модуль специально отделяет такие находки от предположительных адресов и по умолчанию отключает менее надёжную ступень догадок.

Разумеется, открытость данных не отменяет вопросов этики. Наличие адреса в репозитории ещё не означает согласие на массовую рассылку. Поэтому resume2human не отправляет письма автоматически, не создаёт кампании и не пытается заменить рекрутера или CRM. Окончательное решение - кому писать, что писать и нужно ли писать вообще - остаётся за пользователем.

Скоринг действительно раздавал 50 очков

За неделю выяснилось, что часть ошибок скрывалась не в сборщиках данных, а в математике оценки. Один из факторов добавлял 50 баллов за факт, который фактически присутствовал почти всегда. Формально расчёт выглядел корректно, но на практике этот показатель перестал различать сильные и слабые совпадения.

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

Нашлись и ошибки, не связанные напрямую с доменом. Флаки-тест проверял не то условие, которое предполагалось. В одном месте команда столкнулась с `Argument list too long`, из-за чего витрина ссылок показывала девять несуществующих изображений. На русской раскладке не срабатывал сценарий с Ctrl+C. А интернационализация без gettext привела к тому, что русские строки стали одновременно и отображаемыми значениями, и ключами переводов.

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

Из поисковика - в рабочий инструмент

Первоначально приложение заканчивалось на файле с вакансиями и найденными контактами. Но после нескольких самостоятельных прогонов стало понятно, что пользователю необходима следующая часть процесса: сохранение откликов, статусы, напоминания и история взаимодействий.

Так появились воронка откликов и два шаблона сценариев. Для небольших выборок добавили интервал Уилсона, чтобы оценка конверсии не выглядела убедительной только из-за двух случайных успешных ответов. Отчёты начали открываться обратно в приложение, а не существовать как одноразовый экспорт.

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

Статистика недели теперь включает не только число найденных вакансий. Важны доля отфильтрованных позиций, количество подтверждённых контактов, переходы по этапам воронки и реальные ответы. Такой подход полезнее простого счётчика: он показывает, где именно теряется эффективность - на этапе поиска вакансий, анализа резюме или коммуникации.

Доверие строится на проверяемых деталях

Отдельное внимание пришлось уделить документации. В README уже содержались обещания, которые перестали соответствовать функциональности, однако это обнаружилось лишь при подготовке обновлённой витрины проекта. Между изменением поведения программы и исправлением описания прошло два pull request.

После этого появились дополнительные проверки: контроль хэшей SHA-256, подписи артефактов и обработка ситуации, когда ссылка на важный файл возвращает 404. Даже техническая витрина должна быть честной: несуществующие изображения, устаревшие инструкции и неработающие ссылки быстро подрывают доверие сильнее, чем один исправленный баг его восстанавливает.

Текущие ограничения сформулированы точнее. Приложение по-прежнему не рассылает письма от имени пользователя и не превращает поиск вакансий в автоматизированную кампанию. Оно также не обещает, что найденный адрес будет актуален или что человек действительно участвует в найме. Задача программы - сократить рутинный поиск и предоставить проверяемые основания для следующего шага.

Что изменилось в подходе

Главный вывод недели оказался не столько техническим, сколько продуктовым. Инструмент, который только собирает вакансии, остаётся поисковиком. Пользователь оценивает его не по количеству найденных карточек, а по тому, насколько быстро он может перейти от резюме к осмысленному контакту и понять результат.

Поэтому сервисы для поиска работы всё чаще должны объединять несколько этапов: сбор вакансий, сопоставление требований, выявление релевантных сотрудников, фиксацию отклика и последующую аналитику. При этом автоматизация не должна скрывать логику принятия решений или подменять человека в коммуникации.

Дальнейшее развитие resume2human будет связано с качеством данных, прозрачностью скоринга и устойчивостью коллекторов. Важны не только новые источники вакансий, но и аккуратная отбраковка, защита от дубликатов, проверка доступности контактов и корректное отображение ограничений.

Неделя показала простую вещь: хороший продукт рождается не из списка функций, а из столкновения с реальным процессом. Git неожиданно стал каналом поиска контактов, один неверный коэффициент обесценил часть скоринга, а пустая таблица в базе данных превратилась в полноценную воронку откликов. Именно такие находки заставляют пересматривать архитектуру и превращают эксперимент в практический инструмент.

Прокрутить вверх