Неделя после Хабра: почта инженера нашлась в его коммитах, а скоринг раздавал 50 баллов бесплатно
Шесть дней назад я рассказывал о resume2human - Windows-приложении, которое превращает резюме в подборку подходящих вакансий, а затем пытается найти по каждой из них живых людей: рекрутера, нанимающего менеджера или инженера, способного подсказать правильный контакт. За неделю проект получил 21 коммит в девяти pull request, а количество тестов выросло с 345 до 746.
При этом примерно половина первоначальных обещаний изменилась. Не потому, что идея оказалась несостоятельной, а потому, что реальный запуск быстро показал: одного поиска вакансий недостаточно. Важно понимать, что происходит с откликом дальше, насколько достоверны найденные данные и можно ли вообще написать конкретному человеку.
Проект задуман как инструмент для тех, кому нужен не очередной агрегатор, а более прямой поиск работы в IT. Он анализирует резюме, сопоставляет его с вакансиями и предлагает несколько контактов по каждой релевантной позиции. При этом программа не рассылает письма автоматически, не требует платных API и не пытается заменить человека в принятии решений.
Главное открытие недели: Git как открытая база контактов
Первая версия механизма отвечала на вопрос: "Кто участвует в найме?" Но на практике возникал следующий: "Как с этим человеком связаться?" Профиль в социальной сети или страница компании далеко не всегда позволяли отправить сообщение напрямую.
Коммерческие сервисы вроде ContactOut, Lusha, Apollo и RocketReach решают эту задачу через платные базы. Но для инженеров нашёлся другой путь. В каждом Git-коммите есть поле `author.email`. Оно присутствует всегда, даже если в профиле GitHub позднее включён режим скрытия адреса.
Старый коммит, созданный несколько лет назад с личного компьютера, мог содержать настоящий адрес разработчика. Он оставался в истории репозитория, форках, зеркалах и публичных архивах. Поэтому Git оказался своеобразной открытой базой инженерных контактов, о которой многие забыли.
В resume2human добавили отдельный бесплатный уровень поиска таких адресов. Он не гарантирует, что найденная почта актуальна, зато показывает контакт, который человек когда-то опубликовал сам в процессе работы. Подробное описание подхода и ограничений можно найти в материале о поиске IT-контактов через Git-коммиты.
Здесь особенно важны этические границы. Адрес из коммита не превращает его владельца в объект для массовой рассылки. Это лишь дополнительная подсказка для персонального обращения, составленного вручную и по конкретной вакансии. Автоматическая отправка писем в проект по-прежнему не планируется.
Почему половина работы - отбраковка
После появления нового источника контактов стало очевидно: найти адрес - только начало. Нужно проверить, связан ли он с нужным человеком, относится ли коммит к актуальному профилю, не является ли адрес техническим, временным или общим для команды.
Поэтому значительная часть модуля посвящена фильтрации. Система отбрасывает подозрительные домены, дубликаты, адреса роботов, служебные ящики и контакты, которые нельзя надёжно сопоставить с конкретным специалистом. Иногда полезнее показать один проверенный вариант, чем десять случайных.
Пользователь получает объяснимый результат: почему вакансия подошла, откуда взялся контакт и какие признаки повлияли на итоговую оценку. Это принципиально отличается от "чёрного ящика", который просто выдаёт список кандидатов без возможности проверить логику.
Скоринг раздавал 50 баллов за пустоту
Самый неприятный дефект обнаружился в системе оценки совпадения резюме и вакансии. Один из компонентов должен был проверять покрытие требований. Однако для пустого множества сработало математическое правило: пустое множество считалось покрытым полностью.
В результате вакансия без заполненного набора требований могла получить дополнительные 50 баллов. Формально функция возвращала корректный результат, но смысл оценки разрушался: отсутствие данных интерпретировалось как идеальное соответствие.
Проблему исправили тестами на пустые входы и пересмотром самой модели скоринга. Теперь отсутствие информации не даёт бонуса. Это кажется очевидным только после обнаружения ошибки; на практике именно такие граничные случаи часто проходят мимо основных сценариев.
Отдельно выяснилось, что локация не должна быть самостоятельным слагаемым. Если прибавлять баллы просто за совпадение города, можно искусственно поднять вакансию, которая по навыкам не подходит. География теперь работает как ограничение или дополнительный фильтр, но не маскирует отсутствие профессионального соответствия.
Три бага, из-за которых поиск проверял не то
За неделю нашлись и более прозаичные проблемы. Один флаки-тест утверждал, что проверяет определённое поведение, хотя на деле контролировал другой участок логики. Такой тест создавал ложную уверенность: зелёный результат не означал, что нужный сценарий действительно защищён.
Вторая ошибка появилась при формировании командного вызова. Слишком длинный список аргументов приводил к `Argument list too long`, после чего витрина показывала ссылки на девять несуществующих изображений. Пользователь видел аккуратный отчёт, но часть ссылок вела в никуда.
Третья проблема касалась интерфейса. Комбинация Ctrl+C не работала при русской раскладке клавиатуры. Для приложения, где нужно копировать адреса, имена и фрагменты писем, это превращалось в раздражающий ежедневный дефект.
Одновременно была переработана локализация. Вместо отдельной инфраструктуры gettext русские строки временно используются как собственные ключи. Решение не идеально для большого продукта, но оно проще, прозрачнее и не требует преждевременно усложнять архитектуру.
От поиска вакансий - к воронке откликов
Первоначально программа заканчивалась отчётом с вакансиями и контактами. После нескольких реальных запусков стало ясно, что пользователю нужна хотя бы базовая история действий: отправлен ли отклик, был ли ответ, требуется ли напоминание.
Так появилась воронка со статусами, двумя шаблонами сообщений, интервалом для повторного обращения и шестью аналитическими разрезами. Это ещё не полноценная CRM, но уже рабочий способ не потерять отправленные письма и видеть результат поиска.
Для статистики применён интервал Уилсона. Он лучше простого процента показывает неопределённость на небольших выборках: один ответ из двух писем не должен выглядеть так же надёжно, как сто ответов из двухсот. В инструменте, который помогает принимать решения о поиске работы, честность таких чисел важнее эффектных диаграмм.
Доверие начинается с документации
Отдельное внимание уделили отчётам. Теперь сформированные результаты можно открыть повторно, проверить состав найденных данных и сопоставить их с исходной вакансией. Для файлов добавляется SHA-256, а важные части отчёта подписываются, чтобы было заметно изменение содержимого.
Впрочем, именно здесь проявилась ещё одна неприятная деталь: README продолжал обещать старое поведение. Код уже изменился, а документация всё ещё утверждала, что инструмент не ведёт статусы. Исправление потребовало не новой функции, а синхронизации описания с реальностью.
Так появился принцип: доверие формируется не только алгоритмами. Если приложение показывает 404 в самом важном абзаце, не объясняет происхождение контакта или оставляет устаревшие обещания, пользователь перестаёт верить даже корректным результатам.
Что изменилось в ограничениях
По-прежнему сохраняются несколько принципиальных правил. Программа не отправляет письма вместо пользователя и не создаёт массовые рассылки. Она не гарантирует, что найденный адрес действителен сегодня. Данные из открытых источников могут устареть, принадлежать старому аккаунту или относиться к другому человеку с похожим именем.
При этом ограничение "не хранить историю откликов" больше не действует: приложение получило воронку, статусы и напоминания. Также появилась отдельная ступень предположительных адресов, но она отключена по умолчанию и маркируется отдельно от подтверждённых контактов.
Для тех, кто хочет самостоятельно найти IT вакансии и проверить подход к анализу резюме онлайн, важна последовательность: сначала сопоставить навыки, затем проверить работодателя, после этого найти контакт и только потом писать персональное сообщение. Такой порядок снижает риск ошибочных обращений.
Что дальше
Следующий этап - улучшить качество сопоставления вакансий, не превращая систему в непрозрачный ИИ-рейтинг. Планируется точнее разделять обязательные и желательные требования, учитывать давность опыта и лучше распознавать близкие названия ролей.
Отдельное направление - поиск сотрудников в IT со стороны небольших компаний и команд, у которых нет бюджета на дорогие сервисы для рекрутинга. Но здесь особенно важно не перейти грань между полезной автоматизацией и массовым сбором персональных данных.
Итог недели оказался полезнее первоначального плана. Проект получил больше тестов, обнаружил ошибки в математике, интерфейсе и документации, а также превратился из простого поисковика в зачаток системы сопровождения откликов. Главное изменение состоит не в количестве новых функций, а в понимании: хороший инструмент должен не только находить вакансии и контакты, но и честно показывать, насколько этим результатам можно доверять.


