Журнал изменений
GitHubКаждое значимое изменение, релиз за релизом. Тот же файл публикуется в репозитории и переведён на все 19 языков.
[1.228.3] — 2026-08-30
Исправлено — ассистент по документации не отвечал по-английски, названия компаний из Telegram приходили обрезанными, а мониторинг не мог увидеть, что сервис жив.
Исправлено
-
Ассистент отвечал «подходящих разделов справки не найдено» по-английски, хотя тот же вопрос по-русски работал. Поиск был исправен — виноват сборщик контекста. В
buildAskPromptстоялоif (ctx.length + sec.body.length > MAX_CONTEXT) break— именноbreak, поэтому один переросший раздел обрывал цикл и оставлял контекст пустым, а ассистент честно сообщал, что у него ничего нет. Английский §5 вырос до 16 081 байта при бюджете 14 336 (в том числе потому, что v1.228.0 добавила в негоtelegram_channels), русский весил 13 009 и влезал. Ранжирование в обоих языках одинаковое — §5 первый, — различался только размер.Две правки: раздел свыше 6 КБ теперь делится по границам
###, поэтомуtelegram_channelsстал отдельным чанком на 1 340 байт и занимает первое место в обоих языках; а переросший раздел пропускается или усекается, но больше не обрывает цикл. Руководство разбилось на 75 чанков вместо 32. -
Метка компании в Telegram давала предложение вместо названия.
Компания: FinCore Technology (продуктовая разработка, высоконагруженные системы)превращалось вFinCore Technology (продуктовая разработка, высоконагруженны— обрезано на 60 символах, посреди слова. Три строки из 141. Теперь имя заканчивается на первом разделителе, вводящем описание: тире в пробелах (поэтомуCoca-Colaуцелеет), запятая, точка с запятой, вертикальная черта или открывающая скобка; остаточное ограничение падает на границу слова. Этот источник приписывает компанию как факт, и обрезанное предложение неверно ровно так же, как выдуманное имя, — только менее заметно.
Добавлено
GET /api/ping— проба живости, не раскрывающая ничего. Только{ ok, version }./api/healthсообщает абсолютные пути, настоящее имя владельца профиля и то, какие API-ключи заданы: это законно для аутентифицированного оператора и недопустимо для открытого интернета. У мониторинга за Basic-аутентификацией до сих пор вообще не было способа увидеть, что сервис жив.
[1.228.2] — 2026-08-30
Исправлено — поиск из двух слов в /api/scan-results искал фразу, а не слова, и сильно недобирал.
Исправлено
-
?q=теперь сопоставляет каждое слово по отдельности, а не фразу целиком. Запрос был однимincludes(q)по заголовку, компании и локации, поэтомупродакт менеджернаходил только строки, где эти два слова стоят именно рядом, — 32 из 162, которые содержат оба. «Менеджер продукта» и «Менеджер по развитию продукта» были для него невидимы: те же слова, но в другом порядке или с наполнителем между ними.Так узкое совпадение превращается в неверный ответ. Telegram-ассистент на просьбу найти всех продуктовых менеджеров сообщил 9 — честно, потому что 9 ему и ответил эндпоинт. Его число было правдивым, а вот число эндпоинта — нет. Порядок слов и то, что стоит между ними, человек, набирающий два слова, закреплять не собирался.
Сопоставление идёт по И, так что расширение не стоит точности: строка обязана содержать каждое слово.
менеджер разработчиквернёт ноль, а не объединение.
[1.228.1] — 2026-08-29
Исправлено — висячий симлинк в репозитории, молча обрезавший деплой.
Исправлено
-
.claude/skills/refero-designбыл отслеживаемым симлинком на путь, которого здесь никогда не было. Он указывал на../../.agents/skills/refero-design, то есть на.agents/в корне репозитория; такой директории нет, а сама ссылка попала сюда в пакете паритета v1.118.0 с машины, где вложенность папок была другой. С тех пор любой, кто клонировал репозиторий, получал битую ссылку.И она не была безобидной. rsync прерывается на ней посреди передачи — сегодняшний деплой отчитался об успехе, пока сервер продолжал работать на прежней версии, и расхождение всплыло лишь потому, что версию проверили после. Родительский
node test-all.mjsтоже падает, если чекаут web-ui лежит внутри его дерева: копия фикстур обходит рабочую директорию и не может сделать stat по ссылке. Ссылку никто не использовал: единственные совпаденияreferoв репозитории — польское слово preferowany.
[1.228.0] — 2026-08-29
Добавлено — Telegram-каналы как источник сканирования и постраничный режим запроса у /api/scan-results.
Добавлено
-
Telegram-каналы стали сканируемым источником. Отдельный блок
telegram_channels:вportals.ymlперечисляет каналы; каждый читается через публичный веб-превьюhttps://t.me/s/<канал>. Реестр: 85 → 86 источников (81 EN + 5 RU),ALL_ADAPTERS80 → 81.У Telegram нет своего RSS, а Bot API не позволяет читать канал, которым бот неадминистрирует. Оба очевидных пути закрыты. Превью
/s/— обычный HTML с сервера: без входа, без JS, без куки. Проверено на 16 каналах: 15 отдали по 20 постов на голый GET.channel:принимает любую запись —rabotaphp,@rabotaphp,https://t.me/rabotaphp, даже ссылку на конкретный пост. Парсер опирается на три вещи, которые редизайн Telegram сдвинет в последнюю очередь:data-post="<канал>/<id>"(он же разбивает страницу на посты и несёт единственный стабильный URL поста), контейнер текста сообщения и ISO-дату<time datetime>. -
У
GET /api/scan-resultsпоявился постраничный режим запроса.?q=<текст>&limit=50[®ion=ru|en][&set=filtered|fresh][&offset=N]возвращает{ total, returned, offset, limit, set, rows }, гдеtotal— количество ДО пагинации. Без параметров роут по-прежнему отдаёт снимок целиком: от этой формы зависит таблица#/scan.
Исправлено
- Telegram-ассистент отвечал по доле данных. Его навык уже указывал на
/api/scan-results, но роут умел отдавать только весь снимок — около 2 МБ на реальной машине, что не влезает в контекст агента. На «найди все Продуктовый менеджер» он сообщил 9 совпадений там, где в снимке их были сотни, и честно сказал, что «работает с ограниченным локальным индексом». Это было правдой: эндпоинт он видел, а съесть не мог. С постраничным режимом тот же вопрос стоит 2 КБ и возвращает честныйtotal. Навык тоже переписан: он предлагал сводить новые посты, то есть указывал наfresh(только последний прогон) вместоfiltered(всё оставленное).
Примечания
- Пост канала — это проза, а не запись о вакансии. В отличие от всех прочих источников здесь нет структурированных полей: источник берёт заголовок из первой содержательной строки, компанию/город/вилку — по явным меткам («Компания:», «Локация:», сумма с валютой), а полный текст кладёт в описание. Отделять настоящие вакансии от рекламы и дайджестов оставлено существующему
title_filter— тому же, что уже настроен для других источников. Это лиды, а не готовый список. - Компания никогда не угадывается. Без метки «Компания:» запись атрибутируется каналу (
@rabotaphp), потому что неверный работодатель попадает в трекер как факт. - Пустой разбор — это ошибка, а не «вакансий нет». На закрытый или несуществующий канал t.me отвечает редиректом; вернуть ноль строк значило бы показать спокойный день и навсегда спрятать опечатку в конфиге.
jobGeeksиз исходного списка ведёт себя именно так (HTTP 302) и намеренно не добавлен. - Определение удалёнки использует Unicode-границу слова вместо
\b:\bработает только с ASCII, поэтому пробел перед кириллическим словом границей не является и\bудалникогда не совпадал с «удалёнка» — та же ловушка, что и в фильтре заголовков в v1.227.3, здесь пойманная тестом до релиза. - Настроено и проверено живьём 15 каналов: 299 постов, 15/15 каналов,
salary_pmдал 13 вилок из 20. 30 новых тестов. Тесты: 2865 → 2895. - Счётчики тестов в README подскочили на сотни — и нет, этот релиз их не добавил. В локализованных README лежали замороженные значения: 1856 / 1945 / 1955 / 549 / 419 / 284 / 2527 — каждое устарело со своего релиза, и некоторые противоречили бейджу на той же странице. Теперь везде 2895, и это проверено прогоном набора, а не переписыванием бейджа. Так же устарели Playwright (70 / 90 / 12 → 101), smoke e2e (20 → 21), модули маршрутов (12 / 32 → 37), потоки smoke (12 → 22) и число файлов тестов (218 → 329). Строка
Итогодублировала счётчик юнитов и потому не сходилась с тремя наборами ниже — теперь там настоящая сумма (3040).
[1.227.5] — 2026-08-29
Исправлено — региональный скан выедал память сервера, и один Playwright-сьют флейкал на собственном teardown.
Исправлено
- Региональный скан ронял сервер по OOM.
ru-scannerнакапливал все сырые хиты по всем запросам и дедуплицировал с фильтрацией только в самом конце. Список запросов намеренно состоит из близких синонимов (Golang,Go разработчик,Golang разработчик,Senior Go…), поэтому одна и та же вакансия возвращается по разу на запрос, и массив держал кратно больше объектов, чем уникальных — вместе с описаниями, которые составляют основную массу объекта и почти все всё равно отсеиваются фильтрами. Замерено: 742 МБ кучи на реальном прогоне из 21 запроса. Сервер ограничивает кучу Node 490 МБ (V8 считает лимит от 956 МБ RAM машины), поэтому скан валил сервис сFATAL ERROR: Reached heap limit— четыре раза за сутки. Теперь дедуп и фильтрация идут по каждому запросу, и тот же прогон уложился в 177 МБ, минус 76%. Отчётные числа не изменились: уникальный итог несётSetиз URL-строк, так что «Total found» значит ровно то же, что и раньше. net::ERR_SOCKET_NOT_CONNECTEDроняла CI случайным образом. Три Playwright-сьюта вызываютwindow.stop(), чтобы оборвать незавершённые запросы перед проверкой «консольных ошибок нет». Chromium сообщает об одном и том же намеренном действии тремя именами в зависимости от состояния сокета:ERR_ABORTEDпри отмене запроса,ERR_EMPTY_RESPONSEв полёте иERR_SOCKET_NOT_CONNECTED, когда сокет уже разорван. Общий фильтр знал только первые два, поэтому один и тот же teardown ронял прогон наугад. Всплыло на прогоне по локалям вtr— сьюте с наибольшим числом навигаций, — тогда какplaywright-formsиplaywright-smoke, которые тоже вызываютwindow.stop(), были в одном неудачном прогоне от того же.
Примечания
- Почему скан начал падать только сейчас. Список запросов вырос с 14 до 21, когда добавили поиски продакт-менеджера. Память старой реализации росла с общим числом хитов, поэтому +50% запросов пробили потолок машины. С новыми запросами всё в порядке — они лишь вскрыли схему выделения памяти, которая давно была в одном изменении конфига от отказа.
- Правка дедупа сохраняет поведение, и это проверено, а не заявлено.
tests/ru-scanner-dedup-order.test.mjsфиксирует неудобное направление — более поздний дубликат, НЕ проходящий фильтры, обязан вытеснить более ранний прошедший, потому что старый проход в конце оставлял только последнюю копию и затем её отфильтровывал — и прогоняет 200 рандомизированных сверок против прежней реализации «накопить, потом отфильтровать». - Фильтр консоли остаётся узким. Безобидно только семейство отменённых запросов. Отказ в соединении, сбой DNS, сброс, любой 5xx и любое необработанное JS-исключение по-прежнему валят проверку — это закреплено новыми тестами.
- Две гипотезы были проверены и отброшены, а не отправлены в релиз: таймаут Caddy (конфиг чистый,
flush_interval -1для SSE верен) и дефолтный 5-минутныйrequestTimeoutNode (уменьшенная репродукция показала, что он длинный стриминговый ответ не рвёт). Настоящей уликой сталReached heap limitв журнале. Тесты: 2860 → 2865.
[1.227.4] — 2026-08-29
Исправлено — word: / stem: всё ещё игнорировались в content_filter; v1.227.3 починил только фильтр заголовков.
Исправлено
content_filterне учитывал префиксы. v1.227.3 научилtitle_filterродительским префиксамword:/stem:, ноcontent_filterостался на собственном сыромlower.includes(k), так что запись с префиксом там по-прежнему сопоставлялась как буквальный текст"word:java"— та же молчаливая пустышка, на один фильтр дальше.content_filterчитает ОПИСАНИЕ вакансии, и его умолчание всегда было простой подстрокой — именно поэтому голый негативjavaотбрасывает всё, где просто упомянут «JavaScript»; префикс и есть способ отказаться от этого для одной записи. Портирован родительскийcompileContentKeyword: он использует ту же машинерию префиксов, но намеренно не привязывает короткие ключи к границам слова — фильтр заголовков привязывает аббревиатуры из 2–3 букв, потому что «COO» внутри «Coordinator» всегда ошибка, тогда как короткая последовательность внутри абзаца прозы обычно осмысленна (aws,gcp,sql,go).
Примечания
- Найдено в AI-ревью PR v1.227.3, которое заметило, что код не покрывает то, что заявляет его же комментарий — там было «
title_filter/content_filter», хотя подключён был только путь заголовков. Теперь комментарий явно разделяет: префиксы работают в обоих фильтрах, автопривязка аббревиатур — только в заголовках. - Тоже проверено по тому ревью и не изменилось: перевод правила для аббревиатур 2–3 букв с
\bна Unicode-границу поведенчески идентичен для ASCII и строже только там, где нужно —COO_leadиcoo1по-прежнему сохраняются (подчёркивание и цифра — символы слова в обоих вариантах),Coordinatorсохраняется, «Директор COO» и «VP «Продукт»» корректно отбрасываются. Проверено 14 краевых случаев. - Записи
content_filterбез префикса сохраняют прежнее сопоставление байт в байт, пустое/отсутствующее описание по-прежнему проходит, а голыйword:/stem:не матчит ничего вместо всего. 6 новых кейсов вtests/content-filter.test.mjs. Тесты: 2852 → 2858.
[1.227.3] — 2026-08-29
Исправлено — префиксы word: / stem: в фильтре заголовков молча игнорировались, превращая эти строки фильтра в пустышку.
Исправлено
- web-ui не реализовывал родительские префиксы
word:/stem:.title_filter(иcontent_filter) по умолчанию сопоставляют подстроку без учёта регистра — именно поэтому голый негативinternотбрасывает и «International Product Manager», и «Internal Tools Engineer». Вместо смены умолчания (ломающей все настроенные установки) родитель сделал точность опциональной для каждой записи:word:internматчит только целое слово,stem:agentдолжен начинать слово и может продолжаться (отделяя «Agentforce» от «Reagents»). В web-ui не было ни того, ни другого, поэтому запись с префиксом сопоставлялась как буквальный текст"word:intern", которого нет ни в одном заголовке вакансии. Строка становилась молчаливой пустышкой: тот жеportals.ymlкорректно фильтровал через CLI и совсем не фильтровал здесь, так что все стажёрские вакансии, которые пользователь исключил, всё равно попадали в таблицу#/scan. Портировано из родительскогоtitle-keywords.mjs, включая границу слова с учётом Unicode (\p{L}\p{M}\p{N}_) вместо\b, который работает только с ASCII и матчил внутри слова в заголовках с диакритикой и кириллицей.
Примечания
- Найдено при проверке живого
portals.yml, куда только что добавилиword:internименно чтобы голыйinternперестал выбрасывать «International Product Manager». В CLI префикс работал; web-ui тихо оставлял все стажёрские вакансии. Теперь поведение идентично. - Умолчания не изменились. Запись без префикса сохраняет прежнее сопоставление: подстрока для фраз и всего, что содержит не-буквы (
.NET,SAP,L&D), и привязка к границам слова для аббревиатур из 2–3 букв. Голыйword:/stem:без продолжения считается опечаткой и не матчит ничего — как негатив пустой шаблон совпал бы с любым заголовком и зарубил бы весь скан из-за одного случайного двоеточия. - Правило для аббревиатур 2–3 букв переведено на ту же Unicode-границу: раньше оно использовало
\b, из-за чегоcooиword:cooрасходились на не-ASCII заголовках — два написания одного правила. - 6 новых кейсов в
tests/title-filter.test.mjs. Тесты: 2846 → 2852.
[1.227.2] — 2026-08-29
Исправлено — #/config уезжал вбок на узких телефонах.
Исправлено
- MOBILE-1:
#/configвыходил за экран по горизонтали на вьюпортах ≤ 352 px. Каждое поле-селект несло инлайновыйmin-width: 300px. Инлайновый стиль перебивает таблицу стилей, поэтому контрол не мог ужаться вместе с контейнером: на вьюпорте 320 px правый край селекта оказывался на 353 px, страница получала горизонтальную прокрутку, а контролы уезжали за правый край. Затронуты все 18 селектов провайдеров/моделей (cfg-llm-providerи всеcfg-*-model). Теперьmin-width: min(300px, 100%)+max-width: 100%: комфортные 300 px применяются только когда есть место. Устройства на пороге и ниже: iPhone SE 1-го поколения (320 px), старые Android, внешний экран Galaxy Fold.
Примечания
- Почему все прошлые мобильные прогоны это пропускали. На 360 и 375 px запаса ровно хватает, чтобы overflow не проявился, а Playwright-наборы работают в окне 1280 px. Ни один тест в CI никогда не мерил вьюпорт уже 375 px. Новый
tests/playwright-narrow-viewport.mjsпроходит маршруты с формами на 320 px и падает на любом горизонтальном overflow, называя в сообщении самый широкий элемент-нарушитель; второй кейс фиксирует, что ни один селект#/configне выходит за вьюпорт. Сначала было проверено, что тест воспроизводит баг (scrollWidth 353 > clientWidth 320, 18 селектов с правым краем 353). Playwright: 99 → 101. - Известно и намеренно пока не под гейтом: 280 px (внешний экран Galaxy Fold) всё ещё уезжает примерно на 5 px, но по другой причине — длинный контент внутри блоков
<details>карточки конфига и сайдбар 256 px против вьюпорта 280 px, а не инлайновыйmin-width, который чинит этот релиз. Переверстка под ширину, которой не заявляет ни один массовый телефон, — отдельная работа; списокWIDTHSв сьюте к ней готов. - Также исправлен QA-промт v1.227.1, где маршрут фоллоу-апа был назван
#/modes/followup. Mode-страницы регистрируются «голым» слагом (Router.register(cfg.slug)), поэтому маршрут —#/followup, а#/modes/followupкорректно отдаёт 404. Только документация. - Юнит-сьют без изменений — 2846 (новое покрытие браузерного уровня).
[1.227.1] — 2026-08-29
Исправлено — разбивка источников в справке не сходилась сама с собой, а GitHub-баннер печатался в приложении сырой разметкой.
Исправлено
- §17 давал итог и разбивку, которые не складывались. Во всех бандлах справки было «registry
server/lib/sources/поставляется с 85 адаптерами — 78 английских + 5 русских». 78 + 5 = 83, а не 85; в ja/ko дрейф зашёл дальше — 77 (= 82). Каждый новый источник двигал итог и не трогал слагаемое, и числа расходились уже несколько релизов. Теперь разбивка — 80 EN + 5 RU во всех 17 локалях. Это важнее косметики:docs/help/<lang>.md— единственный корпус для «Ask the docs», поэтому на вопрос «сколько источников поддерживается» пользователь получал два противоречащих числа из одного предложения. - Там же был устаревший якорь версии. «По состоянию на v1.213.0 registry …» дожил в 16 локалях, пока счётчик двигали дважды (83 в v1.219.0, 85 в v1.226.0). Якорь уже чинили вручную в v1.210.1 — и он вернулся. Теперь он убран в пользу формулировки без версии: сам счётчик проверяется против живого реестра, который устареть не может.
- Баннер провайдеров печатался экранированной разметкой вверху
#/help. В v1.225.0/v1.225.1 записано, что его «вырезаетUI.md()(нет поддержки картинок)». Это смешивает две разные вещи:UI.md()экранирует-первым — он экранирует каждый байт источника до любых markdown-преобразований, и это правильная XSS-граница, но противоположность вырезанию. Баннер никто не удалял, потому что этого никто и не пытался, — и все 17 локалей открывали#/help268 символами литерального<p align="center"><img src="https://…. Новый общий вход (server/lib/help-markdown.mjs::stripGithubOnlyBlocks) убирает отдельно стоящие HTML-блоки с картинкой при чтении — и дляGET /api/help/:lang, и для корпуса docs-assistant. В файлах баннер остаётся, поэтому на GitHub витрина по-прежнему рендерится. - Колонка «#» на доске каденции была пустой с v1.117.0. Она читала
entry.appNum, тогда какfollowup-cadence.mjsотдаётnum— поляappNumв payload не было никогда. Теперь читаются оба. Строка «Next up» из v1.227.0 унаследовала ту же ошибку и починена вместе с ней.
Примечания
- Все четыре прожили незамеченными, потому что их ничто не проверяло. Гейты справки (
canonical-docs-coverage,help-ui,help-ru-config-section) считают ЗАГОЛОВКИ — 32 H2 / 121 H3, и ни один тест никогда не читал число внутри абзаца и не смотрел, что реально отдаёт вход справки. Это закрывают два новых сьюта:tests/help-source-counts.test.mjs(заявленный итог равенSOURCES.length; слагаемые равны живому EN/RU-разбиению и дают в сумме итог; в абзаце нет версии) иtests/help-banner-strip.test.mjs(баннер остаётся на диске для GitHub, не переживает strip, первая отрисованная строка каждого бандла — его заголовок, strip остаётся узким, и оба потребителя идут через него). Оба проверены на падение против ровно этих багов до коммита. Тесты: 2837 → 2846. - Реестр, сканер и контракты роутов не менялись; источников по-прежнему 85 (80 EN + 5 RU),
ALL_ADAPTERS80.
[1.227.0] — 2026-08-28
Добавлено — SEEK Гонконг (JobsDB), фильтр «только срочные» для фоллоу-апов и нераскрытые работодатели теперь показывают посредника.
Добавлено
- JobsDB Гонконг через существующий источник Jobstreet/SEEK. Гонконг работает под брендом JobsDB, но стоит на той же платформе SEEK за тем же эндпоинтом v5, поэтому отдельный источник не нужен — достаточно
hk.jobsdb.comв списке разрешённых хостов иsiteKey: HK-Main. Реестр не меняется: 85 источников (80 EN + 5 RU),ALL_ADAPTERS80 — это новый РЫНОК на существующем адаптере, а не новый адаптер. - Фильтр «только срочные» на доске каденции (
#/modes/followup). Новый чекбокс сужает доску до того, что требует действия прямо сейчас. Срочность читается изurgency, которую уже вычислил родительскийfollowup-cadence.mjs(urgent/overdue), и никогда изstatusтрекера — тамapplied/responded/interview, что не совпало бы ни с чем. Когда срочного нет, доска называет ближайший запланированный фоллоу-ап вместо пустого экрана. Логика вынесена в чистый модульpublic/js/lib/followup-view.js— зеркало родительскогоfollowup-view.mjs. - Нераскрытые работодатели атрибутируются агентству-посреднику. Вакансия со скрытым работодателем записывается в трекер как
?, а рекрутёр попадает в колонкуVia.#/trackerпоказывал голый?, поэтому несколько нераскрытых строк были неразличимы, а резолверу логотипов не за что было зацепиться. Теперь такая строка читается как «Не раскрыт · через <агентство>», логотип берётся по имени агентства, и строка находится по этому имени в поиске. Это только отображение — каноническое полеcompanyникогда не перезаписывается рекрутёром. Новый чистый модульpublic/js/lib/company-presentation.js— зеркало родительскогоcompany-presentation.mjs.
Исправлено
- Jobstreet/SEEK обращался к устаревшему эндпоинту. Источник по-прежнему указывал на chalice-search v4 (
/api/chalice-search/v4/search), который SEEK отключил; родитель перешёл на/api/jobsearch/v5/search, а web-ui за ним не последовал. Теперь любая запись Jobstreet/SEEK запрашивает v5. Форма элемента v5 читается нативно (URL строится изid,locations[0].label,advertiser.description,salaryLabel), проекционный параметрsolrFieldsиз v4 убран, а запись, у которой вportals.ymlвсё ещё зафиксирован мёртвый путь v4, сохраняет хост своего рынка, а путь пересобирается на v5 — правки от пользователя не нужны.
Примечания
- Паритет с career-ops 1.30.0 (HEAD родителя
8d64f65→6cc46a4; егоVERSIONвсё ещё 1.30.0 — release-please отстаёт отmain). Не портировано, с причинами: заполнение локации из JSON-LD у iCIMS — у источника iCIMS в web-ui вообще нет хукаenrichDate()(только страницы списка), поэтому чинить нечего; нефатальный stderr CLI (#1974) — раннер web-ui определяет сбой только по коду выхода и никогда не имел этой эвристики; трассировка путей Turbopack — в web-ui нет сборщика; фиксыcv-sync-check— ретранслируются только на чтение и fail-soft; последовательный Playwright вscan.mjs, ответы Block H, guard-ы updater/doctor/update-system, рекурсивная проверка синтаксиса, дашборд на Go и добавленные самотестыjd-skill-gap/verify-cv-facts— только-CLI поверхности, в которые web-ui не заходит, либо самотесты без изменения поведения. Тесты: 2818 → 2837.
[1.226.0] — 2026-08-27
Добавлено — два вьетнамских источника вакансий: ITviec и CareerViet.
Добавлено
- ITviec + CareerViet (Вьетнам). Две вьетнамские площадки с привязкой хоста подключаются к сканеру записями
provider: itviec/provider: careerviet: ITviec (itviec.com, техно) и CareerViet (careerviet.vn, широкий охват). Оба — HTML-скраперы без токенов с SSRF-привязкой хоста, только-HTTPS, fail-soft по компаниям и лимитами страниц. Реестр теперь несёт 85 источников (80 EN + 5 RU),ALL_ADAPTERS80 — оба видны в фильтре «Источник» на#/scan.
Примечания
- Паритет с career-ops 1.30.0 (parentVersion 1.29.0 → 1.30.0). Не портировано (только CLI/сообщество или уже есть): Hired Wall,
/calibrate, clean-markers, паки шаблонов, doctor, pdf/LaTeX и CLI eval/tracker/scan, в которые web-ui не заходит; фикс_html-to-textиroleFuzzyMatchуже были; префиксtitle-filter stem:отложен. Тесты: 2818.
[1.225.1] — 2026-08-27
Исправлено — баннер логотипов провайдеров теперь отображается в README и руководстве.
Исправлено
- Баннер v1.225.0 не показывался на GitHub: у отдельного
images/providers.svgбыл некорректныйfont-family(вложенные двойные кавычки), который GitHub отклоняет;<img>использовал относительныйsrc(raw HTML<img>не разрешает относительные пути на GitHub); а у блока<p>не было завершающей пустой строки, из-за чего он сливался со следующей строкой. Теперь он указывает на отрендеренныйimages/providers.pngпо абсолютному raw-URL, с разделением пустыми строками; SVG также исправлен до валидного XML.
Примечания
- Только доки; без изменений кода и тестов. Витрина cvstart.org и плитки в приложении уже были корректны (встроенный SVG, не этот файл). 2784
[1.225.0] — 2026-08-27
Добавлено — баннер логотипов провайдеров в README и руководстве.
Добавлено
- Баннер логотипов провайдеров. Единый самодостаточный
images/providers.svg— 18 LLM-провайдеров: реальный логотип бренда (simple-icons, CC0) для 11, публикующих иконку, и монограмма в цвете бренда для 7 остальных — теперь возглавляет README (×17) и встроенное руководство. (Само приложение рисует плитки с реальными логотипами; баннер отображается на GitHub, а XSS-безопасный рендерер приложения его убирает.)
Примечания
- Только доки — без изменений кода и тестов; SVG встроенный (без удалённых ресурсов). Источники сканирования без изменений: 83. Тесты: 2784.
[1.224.0] — 2026-08-26
Изменено — плитки LLM-провайдеров теперь показывают реальные логотипы брендов.
Изменено
- Реальные логотипы провайдеров. Плитки провайдеров — поля API-ключей в Настройках, строки Использования, чип дашборда, сводка «Активен» в Настройках, результат ⚡-оценки и приветственный баннер — теперь отображают реальный логотип бренда для 11 провайдеров, публикующих open-source-иконку (Anthropic · Gemini · OpenAI · Qwen · OpenRouter · GitHub · DeepSeek · Kimi · MiniMax · Mistral · Ollama; одно-путевые SVG из simple-icons, CC0). Семь без опубликованной иконки (Hermes · GLM/Z.ai · Grok · Together · Fireworks · BytePlus Ark · Volcengine Ark) сохраняют монограмму в цвете бренда. По-прежнему CSP-безопасно по построению: путь логотипа — встроенная статическая константа, без удалённых ресурсов и без
innerHTML.
Примечания
- Без изменений маршрутов и поведения; тот же API
ProviderLogo.el(slug).provider-logo.jsвырос (встроенные пути логотипов). Источники сканирования без изменений: 83. Тесты: 2784.
[1.223.0] — 2026-08-26
Исправлено — успешная ⚡ live-оценка красилась как ошибка; плюс установка coworker OpenWorker прямо из его GitHub-URL или .zip.
Исправлено
- Тон бейджа результата ⚡-оценки. Успешная live-оценка больше не красится как провал. In-process провайдеры (OpenRouter, DeepSeek, …) не возвращают код выхода подпроцесса, поэтому строгое
code === 0было ложным и любой успех выходил красным (при этом показывая «exit 0»). Тон теперь следует за результатом — красным красит только подпроцесс с ненулевым кодом; live-результат без кода —badge-ok, а суффикс «· exit N» показывается только при реальном коде выхода.
Изменено
- Установка coworker OpenWorker из его GitHub-URL / .zip. В документации coworker теперь описаны установщик одной командой (
curl … | bash, идемпотентный — переиспользует существующие career-ops / web-ui) и три пути установки в OpenWorker (GitHub URL ·.zip· импорт одного файла) вdocs/integrations/openworker.md, встроенной справке §32 (×17) и README.
Примечания
- Закрыта давняя дыра в покрытии: у источника Recruitee появился сквозной тест на фикс v1.214.2 с кавычками вокруг угловой скобки (
>внутри атрибута тега не должен утекать в описание). Источники сканирования без изменений: 83. Тесты: 2783.
[1.222.0] — 2026-08-26
Изменено — подсказки полей расширенных провайдеров (DeepSeek … Volcengine Ark) теперь локализованы на все 17 языков.
Изменено
- Локализация подсказок полей провайдеров. Каждый
config.<slug>Hintдля 11 OpenAI-совместимых провайдеров, добавленных в v1.216.0–v1.217.0 (DeepSeek · GLM/Z.ai · Kimi · MiniMax · Mistral · Grok · Together · Fireworks · Ollama · BytePlus Ark · Volcengine Ark) — подсказки API-ключа, модели и базового URL в разделе Настройки → API-ключи — теперь переведён на все 17 локалей вместо отката к английскому. URL регистрации, id моделей и маркер ⚡ live-eval сохранены дословно.
Примечания
- Поведение не меняется — английский
hintFallbackвfield-specs.jsпо-прежнему страхует отсутствующий ключ, а новый контрактный тест проверяет, что каждыйhintKeyдескрипторов полей резолвится во всех 17 локалях. Источники сканирования без изменений: 83. Тесты: 2779.
[1.221.0] — 2026-08-26
Безопасность — эшелонированная защита от DNS-rebinding на пути fetch сканера.
Безопасность
- HTTP-ядро сканера (
fetchJson/fetchTextвserver/lib/http-json.mjs) теперь резолвит хост каждого источника на реальном сетевом пути и отказывается подключаться, если он резолвится в приватный, loopback, link-local, CGNAT или адрес облачных метаданных — закрывая вектор DNS-rebinding. Хосты сканера уже привязаны к публичным доменам, так что это эшелонированная защита; путь пользовательских URL уже имел более сильную привязку соединения (safe-fetch.mjs). Guard работает только на реальном транспортеfetch— внедрённый в тестахfetchImplникогда не резолвится.
Примечания
- Для нормального сканирования поведение не меняется. Источники сканирования без изменений: 83. Тесты: 2775.
[1.220.0] — 2026-08-26
Добавлено — сканируйте несколько категорий Get on Board из одной записи.
Добавлено
- Запись
getonbrdтеперь может задатьcategories: [programming, operations-management, machine-learning-ai](или одинcategory:) вместо только фидаprogramming; вакансии дедуплицируются по URL между категориями, лимит — 12. Существующие записи не меняются (по умолчанию по-прежнемуprogramming).
Примечания
- Только сервер; SSRF-привязка хоста (www.getonbrd.com) и
redirect:'error'неизменны, а неверный слаг категории отклоняется до запроса. Источники сканирования без изменений: 83. Тесты: 2771.
[1.219.0] — 2026-08-26
Добавлено — Torre в сканере, и теперь каждая метка провайдера корректна.
Добавлено
- Torre (
provider: torre) — пан-латиноамериканский маркетплейс талантов torre.ai, публичный поиск без авторизации с удалёнными вакансиями, которых нет в Greenhouse/Lever/Ashby; один ограниченный запрос на запись. Реестр теперь содержит 83 источника (78 английских + 5 русских). Плюс монограмма активного провайдера в приветственном баннере.
Исправлено
- Сканирование a16z Speedrun завершалось раньше времени на доске с ротацией (короткая страница в середине обхода принималась за последнюю, обрезая до 149 из ~300); теперь доверяет
total_pagesфида. А приветственный баннер определял провайдера по карте из 4 записей (показывая сырой слаг для остальных 14) — теперь использует метку+монограмму из 18; заметка о провайдерах в настройках теперь 18 вместо 7.
Примечания
- Опция нескольких категорий на запись у Get on Board ещё не подключена (нужен рефакторинг на уровне источника). Тесты: 2768.
[1.218.0] — 2026-08-26
Добавлено — значки провайдеров (и правильные имена) везде, где показан провайдер.
Добавлено
- Монограммы провайдеров на чипе дашборда, в сводке «Активен» настроек и в заголовке результата ⚡ оценки.
Исправлено
- Устаревшие метки: три экрана определяли имя из карты на 5 записей (результат оценки помечал любого не-Anthropic провайдера как «Gemini»); теперь используют общий
ProviderStatus.label(18). Счётчик ключей показывал «/ 7» → 18. В список слагов подсказкиLLM_PROVIDERдобавленыark/arkcnво всех 17 языках.
Примечания
- Только клиент, безопасно для CSP. Без изменений сервера. Источники сканирования: 82. Тесты: 2758.
[1.217.1] — 2026-08-26
Усиление тестов — покрытие эндпоинтов для всего списка провайдеров.
Добавлено
- Параметризованный тест
run<Provider>, проверяющий эндпоинт, модель по умолчанию и Bearer-аутентификацию для Kimi, MiniMax, Mistral и Fireworks.
[1.217.0] — 2026-08-26
Добавлено — Ark присоединяется к списку LLM (18 провайдеров). BytePlus Ark и Volcengine Ark — модели Doubao от ByteDance — теперь провайдеры ⚡ живой оценки через тот же OpenAI-совместимый код и базовый URL по региону.
Добавлено
- BytePlus Ark (
ARK_API_KEY, международный) и Volcengine Ark (ARK_CN_API_KEY, Китай) — OpenAI-совместимый Chat Completions черезrunOpenAICompatible(). ЗадайтеARK_MODEL/ARK_CN_MODEL(имя модели Doubao или ваш id эндпоинтаep-…);ARK_BASE_URL/ARK_CN_BASE_URLпереключают регион. Оба встают в порядокauto(последними), с монограммой в настройках и «Использовании». Веб-интерфейс охватывает теперь 18 провайдеров.
Примечания
- Тот же путь доверенной конфигурации + проверки схемы http(s), что и у остальных (никогда не SSRF-валидатор URL вакансий). Источники сканирования без изменений: 82. Тесты: 2755.
[1.216.0] — 2026-08-26
Добавлено — ещё девять LLM-провайдеров, у каждого своя фирменная плитка. ⚡ Живую оценку теперь можно запускать через DeepSeek, GLM (Z.ai), Kimi (Moonshot), MiniMax, Mistral, Grok (xAI), Together, Fireworks или полностью локальный Ollama — достаточно одного ключа, рядом с полем каждого в настройках стоит монограмма.
Добавлено
- Девять OpenAI-совместимых провайдеров. DeepSeek, GLM (Z.ai), Kimi (Moonshot), MiniMax, Mistral, Grok (xAI), Together AI, Fireworks AI и Ollama (полностью локально, без ключа). Задайте ключ — или
OLLAMA_BASE_URLдля Ollama — в Настройках, и провайдер встанет в порядокautoпосле Hermes; закрепите любой черезLLM_PROVIDER. Together также хостит Inkling от Thinking Machines (thinkingmachines/Inkling). Веб-интерфейс охватывает теперь 16 провайдеров живой оценки. - Монограммы провайдеров. CSP-безопасная плитка с инициалом в фирменном цвете отмечает каждого провайдера рядом с полем ключа в настройках и в строке страницы «Использование» — встроенный SVG, без внешних логотипов, ничего не покидает вашу машину.
Примечания
- Базовые URL провайдеров — доверенная конфигурация, проходящая через
runOpenAICompatible()с проверкой схемы http(s) (петля Ollama разрешена), а не через SSRF-валидатор URL вакансий. Источники сканирования без изменений: 82. Тесты: 2752.
[1.215.0] — 2026-08-26
Добавлено — запускайте весь поиск работы из OpenWorker. Новый coworker управляет этим пайплайном из open-source-приложения AI-coworker от Andrew Ng, и встроенная справка теперь его покрывает, так что ассистент «Спросить у документации» может провести вас по шагам.
Добавлено
- Coworker для OpenWorker. Coworker без кода для OpenWorker — Fighter90/career-ops-coworker — выполняет весь поиск работы (скан, оценка, подгонка, трекинг, follow-up) и может запустить этот дашборд, всё на вашем рабочем столе. Это персона из одного файла на 17 языках, установка которой проверена собственным загрузчиком OpenWorker.
- Справка §32 «Run it from OpenWorker» (все 17 локалей) документирует это, чтобы встроенный ассистент «Спросить у документации» и плавающая кнопка справки могли отвечать на вопросы о нём. Также добавлены ссылки в футере лендинга, README, вики и
docs/integrations/openworker.md.
Примечания
- Только документация + сайт — без изменений кода приложения. Источники сканирования без изменений — 82. Набор тестов: 2742.
[1.214.2] — 2026-08-25
Исправлено — общий конвейер HTML→текст (описания Greenhouse / Recruitee) больше не протаскивает атрибуты тега в описание, когда значение атрибута содержит символ >.
Исправлено
- HTML-описания с
>внутри атрибута очищаются корректно. Средство удаления тегов за описаниями Greenhouse и Recruitee использовало наивное совпадение, которое останавливалось на первом>, поэтому тег вроде<a title="salary > 100k">оставлял хвост атрибута (100k">) в описании. Теперь оно уважает значения атрибутов в кавычках (одинарных или двойных), удаляет разметку до декодирования сущностей (чтобы закодированная кавычка внутри атрибута не стала ложным разделителем) и по-прежнему сохраняет литеральный<>в простом тексте.
Примечания
- Набор тестов: 2742. Источники сканирования без изменений — 82. Ничего нового от родителя в этот раз: остальные изменения ретранслируются только на чтение (правки follow-up / weekly-digest / rejection-latency / salary-gap не требуют изменений в web-ui) или не относятся к web-ui (внешний X/Xquik BYO-key плагин, правки CLI/verify). Опциональные пункты — детальные описания SmartRecruiters, пропуск агрегаторов в detect-reposts, префиксы заголовков
stem:/word:, защита от DNS-rebinding — остаются в очереди.
[1.214.1] — 2026-08-25
Исправлено — описания вакансий Ashby теперь обрезаются до той же длины, что у Greenhouse и Recruitee, так что контент-фильтр ведёт себя одинаково на всех трёх досках и одна доска не может раздуть кэш сканирования.
Исправлено
- Описания Ashby теперь соблюдают тот же предел длины, что и другие доски. v1.214.0 подавала тело вакансии Ashby в контент-фильтр, но — в отличие от Greenhouse и Recruitee, которые режут до 4000 символов — у Ashby оно мапилось напрямую без предела (иногда в 4 раза длиннее). Из-за этого одно и то же слово
content_filterмогло совпасть на Ashby, но не на Greenhouse — только в зависимости от позиции в тексте, а одна доска могла добавить сотни КБ в кэш сканирования, который грузит#/scan. Теперь Ashby режется до тех же 4000 символов (его текст уже простой, поэтому он усекается, а не очищается от тегов).
Примечания
- Набор тестов: 2738. Источники сканирования без изменений — 82.
[1.214.0] — 2026-08-25
Исправлено — описания вакансий Greenhouse, Ashby и Recruitee теперь попадают в контент-фильтр, так что фильтры по словам / стране / визе реально совпадают с этими досками; а “Associate <старший титул>” (включая академические звания) больше не относят к entry-level.
Исправлено
- Контент-фильтры теперь работают на Greenhouse, Ashby и Recruitee. Эти доски теперь несут полный текст каждой вакансии как её описание, поэтому
content_filter(или фильтр по словам страны / визы) совпадает с телом вакансии, а не пропускает доску вслепую. Ashby и Recruitee отдают тело в списочном payload бесплатно; Greenhouse уже это делал. Все три очищаются одним общим конвейером HTML→текст. - “Associate Director” / “Associate Professor” — это senior, а не entry-level. Классификатор уровня (используется
skip_tiers:) считал слово “associate” меткой entry-level, даже когда оно предваряет старший титул. Теперь он читает “Associate <старшее существительное>” — включая академические звания (Associate Professor, Associate Dean) — как senior, сохраняя настоящие junior-варианты (Associate Attorney, Associate Editor) как entry-level, и по-прежнему относит ведущий “Intern, Associate Dean” к стажировке.
Примечания
- Набор тестов: 2736. Источники сканирования без изменений — 82. В очереди на потом: опциональное обогащение описаний SmartRecruiters (запрос детали по каждой вакансии), пропуск досок
aggregator: trueв detect-reposts и префиксы заголовков с якорным словомstem:/word:— каждое опциональная настройка, а не изменение поведения по умолчанию. Защита от DNS-rebinding по-прежнему в очереди на отдельный релиз безопасности.
[1.213.0] — 2026-08-22
Добавлено — MyCareersFuture, национальный банк вакансий Сингапура, как источник сканирования. Исправлено — вакансии Greenhouse теперь несут полный текст, чтобы работали контент-фильтры, а удалённые вакансии Ashby больше не прячутся за локацией «только город».
Добавлено
- MyCareersFuture (Сингапур) (mycareersfuture.gov.sg) — новый источник сканирования без токенов для национального государственного банка вакансий Сингапура (Workforce Singapore). Выберите его в фильтре Источник на
#/scanили добавьте компанию сprovider: mycareersfutureи необязательным спискомkeywords(иначе берутся целевые роли из профиля, как у Job Bank). Читает публичный поисковый API, с привязкой к хосту, без ключа.
Исправлено
- Вакансии Greenhouse теперь можно фильтровать по контенту. Доски Greenhouse запрашиваются вместе с полным телом вакансии, декодированным в простой текст как описание — так что
content_filter(или фильтр по словам страны/визы), читающий описание, теперь реально совпадает с вакансиями Greenhouse, а не пропускает их вслепую. - Удалённые вакансии Ashby больше не отсекаются фильтром города. Ashby хранит модель работы (Remote/Hybrid/Onsite) отдельно от города офиса, поэтому полностью удалённая вакансия читалась как, например, «San Francisco» — и фильтр локации, блокирующий этот город, скрывал доступную вакансию. Теперь при удалённой работе к локации добавляется «Remote», а
workplaceTypeважнее устаревшего флагаisRemote, чтобы офисно-привязанная гибридная вакансия не была помечена неверно.
Примечания
- Источники сканирования: 82 (77 английских + 5 русских). Набор тестов: 2724. Защита от DNS-rebinding (проверка разрешённого адреса хоста до подключения) отложена в отдельный релиз — ей нужен собственный дизайн для web-ui, а не прямой порт.
[1.212.1] — 2026-08-21
Исправлено — лендинг cvstart.org недосчитывал источники сканера (показывал 80 и терял Job Bank (Канада)); теперь снова совпадает с 81 в приложении, а сборка сайта громко падает, если эти числа расходятся.
Исправлено
- Счётчик «Источники вакансий» на лендинге снова синхронен с приложением. После v1.212.0 cvstart.org показывал 80 досок, и не хватало нового чипа Job Bank (Канада), тогда как приложение, выпадающий список сканирования и справка перечисляли 81. Лендинг строит список, загружая живой реестр сканера, и один источник не загрузился в этой сборке из-за того, как он подтягивал YAML-зависимость — поэтому был молча отброшен. Теперь Job Bank загружает эту зависимость лениво, так же как остальное приложение делает во время скана, поэтому он всегда на месте.
- Сборка сайта теперь отказывается публиковать несходящийся счётчик. Если реестр перечислит меньше источников, чем есть на диске (признак источника, который не загрузился), сборка падает с понятным сообщением вместо тихой публикации неверного числа.
Примечания
- Поведение приложения не изменилось — в сканере всегда были все 81 источник; затронут был только лендинг. Источники сканирования: 81 (76 английских + 5 русских) — без изменений. Набор тестов: 2687.
[1.212.0] — 2026-08-21
Добавлено — Job Bank (Канада), федеральная национальная доска вакансий. Удалено — EchoJobs (его фид теперь за бот-защитой). Исправлено — доски на Consider снова отдают результаты, а мульти-локационные вакансии Lever больше не скрывают половину локаций.
Добавлено
- Job Bank (Канада) (jobbank.gc.ca) — новый источник сканирования без токенов для федеральной национальной службы занятости Канады, высоконагруженной доски, которую плохо покрывает любой агрегатор. Выберите его в фильтре Источник на
#/scanили добавьте компанию сprovider: jobbankcaи необязательным спискомkeywords(иначе берутся целевые роли из вашего профиля). Читает публичный ATOM-фид, с привязкой к хосту, без ключа.
Удалено
- EchoJobs — выведен. Его публичный фид теперь за бот-защитой и не отдаёт ничего, так что держать его — просто тратить слот сканирования.
Исправлено
- Доски на Consider снова отдают результаты. Consider теперь требует анонимный handshake (GET, который задаёт сессионную куку + CSRF-токен) перед тем, как принять поисковый запрос; без него запрос молча отклонялся и доска выглядела пустой.
- Мульти-локационные вакансии Lever больше не скрывают половину локаций. Lever кладёт один основной город в
location, а остальные — вallLocations; чтение только основного делало вакансию, открытую в Барселоне И Монтевидео, «только-Барселона» (и её ошибочно отсекал фильтр локаций). Теперь обе объединяются.
Примечания
- Мягче темп между страницами (250 мс вместо 150) на постраничных досках — из вежливости к одиночным careers-сайтам. Источники сканирования: 81 (76 английских + 5 русских) — без изменений (Job Bank добавлен, EchoJobs удалён). Набор тестов: 2685.
[1.211.0] — 2026-08-19
Добавлено — Yourator, тайваньская tech-доска вакансий. Исправлено — акцентированные сущности в заголовках/названиях компаний теперь декодируются везде, а компания с акцентом в названии больше не помечается по ошибке.
Добавлено
- Yourator (yourator.co) — новый источник сканирования без токенов для tech- и digital-рынка вакансий Тайваня. Выберите его в фильтре Источник на
#/scanили добавьте компанию сprovider: yourator. Он читает публичный JSON API (без ключа, без браузера), обходит все страницы доски и выдаёт реальную ссылку работодателя (его собственный ATS) с вырезанными трекинг-параметрами.
Исправлено
- Акцентированные именованные сущности теперь декодируются везде. Общий HTML-декодер получил латинские буквы Latin-1 (
é→ é,ç→ ç, …), поэтому европейская доска, пишущаяDéveloppeurилиFrançais, больше не оставляет этот литерал в заголовке, трекере или сгенерированном документе. (Заглавные остаются заглавными —Éэто É, а не é, — а поиск вроде&constructor;теперь разрешается в себя.) - Компания с акцентом в названии больше не помечается по ошибке за то, что находится на своём же домене. «Işık» теперь сворачивается в «isik» и совпадает с isik.com.tr; «Société Générale» совпадает с societegenerale.com. Старая проверка удаляла акцентированные буквы вместо сворачивания к их ASCII-основе.
Примечания
- Источники сканирования: 81 (76 английских + 5 русских). Набор тестов: 2667.
[1.210.1] — 2026-08-19
Исправлено — заголовки вакансий и названия компаний с «&» или кавычками из Habr Career больше не приходят искажёнными.
Исправлено
- Источник Habr Career теперь декодирует HTML-сущности в заголовке и названии компании до того, как они идут дальше. Серверные карточки приходят экранированными («Changellenge >>», «Demand Forecasting & Inventory Optimization», «ООО "М-ТЕХ"»), поэтому недекодированный «&» молча не проходил ваш же фильтр заголовка с «&» — ровно тот симптом, который прошлый релиз закрыл на пяти других досках, — а названия компаний доезжали до трекера и отчётов кривыми. Декодирование сущностей теперь завершено на всех шести затронутых источниках.
Примечания
- Набор тестов: 2644.
[1.210.0] — 2026-08-19
Добавлено — Senjob, первая африканская доска вакансий сканера (Сенегал); более точное совпадение заголовков ещё на пяти досках.
Добавлено
- Senjob (senjob.com) — новый источник сканирования без токенов для Сенегала, первая африканская доска сканера. Выберите его в фильтре Источник на
#/scanили добавьте компанию сprovider: senjob. Он читает публичный список по обычному HTTP (без ключа, без браузера), привязывает каждый запрос к senjob.com и — поскольку парсит HTML — считает список, внезапно давший пусто, сломанной доской (видимой ошибкой), а не страной без вакансий.
Исправлено
- Заголовки с «&» больше не теряют вакансии на пяти досках — на beesite, Cornerstone (csod), Hacker News «Who is hiring», Phenom и TKMS заголовки приходят с HTML-экранированием, поэтому экранированный «&» в должности вроде “R&D Engineer” не проходил ваше же ключевое слово “r&d”, и вакансия молча исчезала (вето “sales & marketing” тоже не срабатывало). Теперь заголовки — и локации Phenom — декодируются перед фильтрацией.
Примечания
- Источники сканирования: 80 (75 английских + 5 русских). Набор тестов: 2643.
[1.209.0] — 2026-08-17
Добавлено — встроенная справка теперь описывает, как записать итог отклика, а «Спросить справку» подсказывает, где это.
Добавлено
- В справке Трекера (§11) во всех 17 языках появился раздел «Записать итог отклика», который проводит по кнопке Итог: выберите, что произошло (отказ / оффер / нанят / отклонён / игнор / прошёл на собеседование), посмотрите предпросмотр и запишите — это фиксирует результат, архивирует отправленные вами резюме и сопроводительное письмо и синхронизирует Статус строки за вас. Плавающий помощник «Спросить справку» читает это руководство, поэтому теперь ведёт вас к этой кнопке, а не только предлагает править Статус вручную.
Примечания
- Каждый справочный бандл теперь 31 H2 / 119 H3 (было 118); стражи паритета обновлены. Только документация — без изменений кода и поведения. Набор: 2625.
[1.208.2] — 2026-08-16
Исправлено — на телефоне кнопки уведомлений и темы больше не накрывают поле поиска.
Исправлено
- В v1.208.1 кнопки верхней панели перестали накрывать заголовок страницы, но на неширокой (хотя и не самой узкой) полоске экрана — особенно в языках с длинными подписями — вся панель по-прежнему втискивалась в одну строку, и кнопки 🔔 и 🌙 могли лечь поверх поля поиска. Теперь кнопки действий (уведомления, тема, Диагностика, Открыть Scan) на телефоне всегда уходят на собственную вторую строку во всю ширину, поэтому поле поиска видно целиком и ничего не перекрывается.
Примечания
- На телефоне кнопки действий верхней панели переезжают на вторую строку во всю ширину, убирая хрупкую полосу «почти полной строки», где раскладка распределяла остаток отрицательного места как наложение. Playwright-страж теперь воспроизводит точный триггер — локаль с длинными подписями в полосе 565–640px — и проверяет, что элементы панели не делят пиксели. Набор: 2621.
[1.208.1] — 2026-08-16
Исправлено — на телефоне кнопки верхней панели больше не накрывают страницу.
Исправлено
- В v1.208.0 кнопки верхней панели (Диагностика, Открыть Scan, уведомления, тема) переносились на вторую строку на узких экранах, но панель сохраняла фиксированную высоту, поэтому перенесённая строка вылезала и ложилась поверх заголовка страницы. Теперь панель растёт под свои строки, а контент идёт под ней.
Примечания
- Фиксированная
heightпанели сталаmin-height, поэтому она растёт под контент на любой ширине (десктоп не изменился). Playwright-страж теперь также проверяет, что панель не вылезает поверх страницы. Набор: 2621.
[1.208.0] — 2026-08-16
Исправлено — приложение теперь помещается на экране телефона: горизонтальная прокрутка ушла.
Исправлено
- На узком экране всё приложение уезжало вбок — верхняя панель, таблицы, статьи справки и вкладки настроек вылезали за правый край. Теперь каждая страница помещается на любой ширине: кнопки верхней панели переносятся на вторую строку, широкие таблицы и блоки кода прокручиваются внутри своей рамки, справка ставит оглавление над статьёй, ряды кнопок и вкладок переносятся, а длинные пути и ссылки переносятся, а не растягивают страницу.
Примечания
- Причина — классическая ловушка flex/grid min-width: auto плюс пара необёрнутых широких элементов; починено через
min-width: 0на grid-элементах,overflow-wrapна markdown/заголовках, прокручиваемую markdown-таблицу и перестроение сетки справки на мобильном брейкпоинте. Playwright-страж проверяет 0 горизонтального переполнения на 375 px по основным маршрутам.tests/playwright-smoke.mjs. Набор: 2621.
[1.207.2] — 2026-08-16
Исправлено — AI-планы и профиль карьерной ориентации больше не отображаются как сырой дамп кода.
Исправлено
- Некоторые модели заворачивают весь ответ в код-ограду
markdown …. Когда так случалось, план развития и профиль ориентации показывались моноширинным блоком кода вместо документа с заголовками и списками. Теперь обёртывающая ограда снимается — только если она охватывает весь ответ и язык явноmarkdown/md, так что настоящий ответ наpython/js/без языка ``` остаётся нетронутым.
Примечания
- Решено один раз в общем шаге очистки LLM (
cleanLlmMarkdown), поэтому выигрывают все AI-маршруты, а вложенные блоки кода внутри ответа сохраняются.tests/llm-output.test.mjs(+3). Набор: 2621.
[1.207.1] — 2026-08-16
Исправлено — на маленьких телефонах лендинг больше не вылезает вбок.
Исправлено
- На узком телефоне первый экран — заголовок, вводная строка и терминал установки — мог обрезаться по правому краю, потому что длинная команда установки и колонки вёрстки не сжимались под экран. Теперь всё помещается на любой ширине; команда установки прокручивается внутри своего терминала.
Примечания
- Также укреплена нестабильная E2E-проверка, которая могла падать из-за временного 404 ресурса: теперь она игнорирует безобидный сетевой шум (favicon / соединение / несостоявшийся ресурс), как и соседние проверки, но по-прежнему ловит реальные ошибки скриптов. Поведение приложения не изменилось. Набор: 2618.
[1.207.0] — 2026-08-15
Добавлено — записывайте итог отклика прямо из трекера.
Добавлено
- В каждой строке трекера появилось действие Итог: выберите, что произошло (отказ, оффер получен, нанят, оффер отклонён, нет ответа, прошёл на собеседование), добавьте необязательную заметку, предпросмотрите итоговый статус и запишите. Запись архивирует отправленные артефакты CV и сопроводительного письма и синхронизирует трекер до канонического состояния — одно детерминированное действие вместо ручной правки трекера.
Примечания
- Новый
POST /api/outcomeретранслирует CLI итогов:dryRun:true— предпросмотр только для чтения (находит строку, сообщает итоговый статус, ничего не пишет); реальный вызов записывает. Безопасность записи: тип итога ограничен известным набором, а каждое текстовое поле отклоняется при управляющих символах до вызова (аргументы-массив, spawn — без shell).tests/outcome-route.test.mjs. Набор: 2618.
[1.206.0] — 2026-08-15
Документация — встроенное руководство теперь описывает пять новейших функций на всех 17 языках.
Добавлено
- Встроенное руководство — и ассистент «Спросить справку», отвечающий по нему — теперь описывает пять недавно добавленных функций: Доктор настройки (Настройки — проверяет CV и профиль на пробелы и оставшиеся демо-данные), Поиск ATS-досок (Порталы — автоматически находит карьерную доску компании), проверку «ещё открыта?» (Трекер — открыта ли вакансия), подсказку «переиспользовать прежнее CV?» (CV Studio — подсказывает, когда уже адаптированное CV подходит к новой вакансии) и Журнал навыков (Аналитика — запись оценок самопроверки). Пять новых подразделов, переведённых на все 17 языков.
Примечания
- Структура руководства выросла до 31 H2 / 118 H3, паритет гарантирован для каждого языка. Обновлена справочная документация:
docs/architecture/API.mdописывает пять маршрутов этих функций, а счётчики маршрутов/версии вCLAUDE.mdиdocs/sdd/CONVENTIONS.mdактуальны (36 модулей маршрутов). Набор: 2610.
[1.205.0] — 2026-08-15
Добавлено — журнал навыков для записи результатов тестов/оценок.
Добавлено
- Новый Журнал навыков (Аналитика → Журнал навыков) позволяет записать самооценку — компания, платформа, навык, оценка % и необязательная заметка — добавляется в
data/assessments.tsv, со списком прошлых записей (новые сверху). Без токенов, детерминированно; формат файла ведёт CLI родительского проекта.
Примечания
- Новый
GET /api/assessments(ретранслирует список JSON по умолчанию изassessment-log.mjs; мягкий отказ{available:false}) +POST /api/assessments(явная запись: поля передаются как аргументы-массив вassessment-log.mjs add). Безопасность записи: любое текстовое поле с управляющими символами отклоняется (TAB сломал бы столбец, перевод строки вставил бы строку) → 400 до записи; оценка/порог ограничены 0–100, длины ограничены.tests/assessments-route.test.mjs. Набор: 2610.
[1.204.0] — 2026-08-15
Добавлено — панель «Доктор настройки» в Настройках, отмечающая незаполненные или демо-данные в CV/профиле.
Добавлено
- Настройки → Доктор настройки теперь без токенов проверяет ваши
cv.mdиconfig/profile.ymlи перечисляет блокирующие проблемы (отсутствующие файлы/поля) и предупреждения (оставшиеся демо/шаблонные данные, зашитые метрики) — чтобы поймать неполную настройку прежде, чем она ослабит сканы и адаптацию. Только чтение; перезапуск одним кликом.
Примечания
- Новый route только для чтения
GET /api/cv-sync-checkретранслируетcv-sync-check.mjsиз родительского проекта, который печатает текст + код выхода (без--json); route легко структурирует его стабильные строкиERROR:/WARN:в{ok, errors[], warnings[]}— успех определяет баннер, а не код выхода. Мягкий отказ{available:false}в автономных установках.tests/cv-sync-check-route.test.mjs. Набор: 2602.
[1.203.0] — 2026-08-15
Добавлено — подсказка «переиспользовать прошлое резюме?» в CV Studio.
Добавлено
- Когда вы открываете сохранённую вакансию в CV Studio, приложение теперь сравнивает её с другими вашими сохранёнными вакансиями (детерминированное совпадение слов, без токенов) и подсказывает, достаточно ли похожа ближайшая, чтобы переиспользовать то адаптированное резюме, переиспользовать с правками или готовить новое — чтобы не пересоздавать с нуля для роли, над которой вы уже работали.
Примечания
- Новый route только для чтения
GET /api/jds/:name/reuseретранслируетjd-similarity.mjsиз родительского проекта (совпадение Жаккара + проверка сениорности; JSON{decision, score, reason}) по разу на каждую прошлую вакансию (fan-out ограничен 25, берётся лучшее совпадение); мягкий отказ{available:false}, если скрипта или прошлых вакансий нет.tests/jd-similarity-reuse-route.test.mjs. Набор: 2594.
[1.202.0] — 2026-08-15
Добавлено — найдите ATS-доску компании прямо на #/portals и начните отслеживать её.
Добавлено
- На #/portals введите название компании — приложение проверит Greenhouse, Ashby и Lever на её публичную доску вакансий (без LLM, без браузера) и покажет доски, которые существуют и сейчас содержат ≥1 вакансию. Один клик добавляет выбранную доску к компаниям, за которыми следит сканер. Проверка только для чтения; запись в
portals.ymlпроисходит лишь при нажатии Добавить.
Примечания
- Новый
server/lib/discover-ats.mjs(проба слага с фиксированным хостом и проверкой charset черезsafeGetс закреплённым DNS, ≤12 проб на запрос, кросс-доменный редирект → не найдено) +POST /api/portals/discover(только чтение) иPOST /api/portals/track(явная запись:withFileLock+ текстовая вставка + перепроверка парсинга + атомарная замена; только известные ATS-хосты, идемпотентно). Переиспользует реестр адаптеров сканера для подтверждения доски и подсчёта вакансий. i18n ×17.tests/discover-ats-resolver.test.mjs+tests/discover-ats-route.test.mjs. Набор: 2588.
[1.201.0] — 2026-08-15
Исправлено — трекер с локализованными или альтернативными заголовками столбцов больше не отображается пустым.
Исправлено
- Если ваш
data/applications.mdиспользует не-английские или альтернативные заголовки — испанскиеempresa/puesto/estado/fecha/enlace, либоposition/stage/link— трекер читал их под неверными ключами и показывал пустые столбцы Компания / Роль / Статус / Дата / Ссылка. Теперь такие заголовки сворачиваются к каноническим именам полей, и трекер отображается правильно. Англоязычный трекер обрабатывается точно как раньше.
Примечания
- Новая карта
HEADER_ALIASESи нормализующая свёртка вparseApplications(server/lib/parsers.mjs); неизвестные или уже канонические заголовки проходят без изменений.tests/tracker-header-aliases.test.mjs. Набор: 2563.
[1.200.0] — 2026-08-15
Добавлено — проверка «ещё активна?» для вакансий на ATS одним кликом прямо в трекере.
Добавлено
- На #/tracker у отклика, чей URL — вакансия Greenhouse / Lever / Ashby / Workday / SmartRecruiters, теперь есть кнопка «Ещё активна?». Один клик спрашивает публичный JSON самого ATS — без токенов, без браузера — и показывает Активна / Закрыта / Неизвестно, чтобы находить мёртвые вакансии, не открывая каждую. Консервативно по умолчанию: только явный 404/410 читается как Закрыта; всё неоднозначное остаётся Неизвестно (никогда ложной Закрыта).
Примечания
- Новые
server/lib/liveness-core.mjs+liveness-api.mjsи route только для чтенияGET /api/liveness?url=(без записей, без LLM). Безопасно к SSRF: URL проходитisValidJobUrl, затем к API ATS обращаемся только черезsafeGet(с закреплённым DNS), с фиксированным хостом и проверенными по charset сегментами пути.tests/liveness-core.test.mjs+tests/liveness-route.test.mjs. Набор: 2557.
career-ops-ui v1.267.1 · page 5/13 · mirror of the project changelog for cvstart.org