Журнал змін
GitHubКожна значуща зміна, реліз за релізом. Той самий файл постачається в репозиторії та перекладений усіма 17 мовами.
Журнал змін
Усі важливі зміни career-ops-ui. Формат — Keep a Changelog, версії за SemVer.
Переклади: 🇬🇧 English · 🇪🇸 Español · 🇧🇷 Português · 🇰🇷 한국어 · 🇯🇵 日本語 · 🇷🇺 Русский · 🇨🇳 简体中文 · 🇹🇼 繁體中文 · 🇫🇷 Français · 🇵🇱 Polski · 🇩🇰 Dansk · 🇸🇦 العربية · 🇩🇪 Deutsch · 🇮🇹 Italiano · 🇹🇷 Türkçe · 🇮🇳 हिन्दी
Примітка щодо перекладу (v1.70.0) — українську додано як одну з трьох нових мов інтерфейсу. Цей файл перекладає найновіші записи; повна історія — в 🇬🇧 англійському CHANGELOG, який є нормативним джерелом.
[1.134.1] — 2026-08-05
Посилення валідації — виправлення, виявлені під час повного аудиту проєкту.
Виправлено
successfactorsбільше не відкидає зібрані вакансії при збої в середині сканування (регресія в портуванні «неактивна дошка = помилка» з v1.134.0) — цикл пагінації не мавtry/catch, тож збій на сторінці 2+ (після успішної сторінки 1) призводив до винятку й губив усе вже зібране; а якщо цей збій був404(вихідstartrowза межі діапазону),en-scannerміг на кілька днів помилково позначити живого орендаря як неактивного. Тепер дзеркалюєphenom/radancy: збій на сторінці 0 досі видає помилку (неактивна дошка), а збій на пізнішій сторінці зберігає часткові результати.- Фільтр-чипи
#/scanтепер керуються з клавіатури (WCAG 2.1.1) — чипи фасетів (і чип «очистити») були елементамиspanз обробником кліку, але безtabindex/ролі, тож користувачі клавіатури та програм читання з екрана не могли до них дістатися чи перемикати їх. Тепер вони маютьrole="button",tabindex="0",aria-pressedі активацію по Enter/Space. - Три захардкоджені англійські рядки тепер локалізовано — підказка бейджа довіри
#/scan, заголовок колонки релокації#/scanта заголовок колонки балу#/dashboardбули голими літералами, яких не бачив паритет-контроль i18n (вони ніколи не були ключами), тож вони залишалися англійськими в кожній неанглійській локалі. Теперscan.trustTip+scan.col.reloc(2 нових ключі) + повторне використанняtrack.col.score, зі статичною перевіркою на рівні коду.
[1.134.0] — 2026-08-05
Паритет із батьківським career-ops v1.25.0.
Додано
- Нове джерело сканування: getManfred (
manfred) — стрічка вакансій в іспанських/європейських технологічних компаніях по всьому борду з опублікованими зарплатами, зwww.getmanfred.com/api/v2/public/offers(без авторизації, прив’язка до хоста + лише HTTPS, повний каталог одним запитом). Джерело + адаптер + CI-ізольований набір тестів (tests/sources-manfred.test.mjs); реєстр тепер налічує 73 джерела = 68 англомовних + 5 російськомовних (ALL_ADAPTERS68). З’являється у фільтрі джерел#/scanта на лендінгу cvstart.org.
Виправлено
- Стрічка a16z Speedrun тихо обрізалася до 50 вакансій (#2404) — стрічка обмежує сторінку 50 елементами, але джерело запитувало
PER_PAGE = 100, тож пагінація зупинялася після першої сторінки. Виправлено на 50. - Неактивні дошки тепер видають помилку, замість того щоб читатися як «живі, але порожні» (#2379) —
cryptocurrencyjobs,phenom,radancy,successfactors: збій запиту, коли жоден запит так і не завершився успіхом, тепер видає помилку (тож перевірка стану#/portalsта сканування фіксують реальний збій), замість того щоб приховувати його за порожнім списком; збій у середині сканування після хоча б одного успіху зберігає часткові результати. - workable тепер використовує публічний widget API (#5ab8425) — перехід на
apply.workable.com/api/v1/widget/accounts/<slug>, який повертає повний список вакансій великого акаунту за один запит, тож великі акаунти більше не обрізаються.
Примітки
- Не портовано (лише для CLI або не дзеркалюється в web-ui): переробка продуктивності групування заголовків для виявлення репостів #2389; виправлення Unicode-ключів компаній (власна дедуплікація трекера web-ui вже безпечна для не-латиниці);
scan --since;cv-facts; аудит-прохід шаблону CV / PDF;doctor; директива щодо недовіреного вмісту в режимах.
[1.133.1] — 2026-08-02
Виправлено
#/funded(Профінансовані компанії) тепер відображає результати — через два баги таблиця завжди показувала «немає профінансованих компаній», навіть коли батьківськийcompany-funded.mjsповертав повний список. (1) Вигляд читав результати зres.candidates, а батьківський скрипт видає їх під ключемcompanies(кожен елемент —{ company, amount, round, funding: { sources: [{ source, url, observed_date }] } }); клієнт тепер читає правильний ключ і мапить реальну форму доказів. (2) Таблиця результатів передавала свої комірки вUI.el('tr', {}, …)як varargs, алеUI.el(tag, attrs, children)приймаєchildrenяк один вузол або масив, тож рендерилась лише перша колонка (Компанія) — тепер комірки передаються як масив. Перевірено в реальному браузері: 11 компаній із чотирьох стрічок відображаються з колонками Компанія / Сигнал фінансування / Джерело / Дата та робочими посиланнями на докази, нуль помилок у консолі. Порожній прохід тепер також показує діагностику по кожному джерелу, щоб тихий новинний день можна було відрізнити від заблокованої стрічки.- Регресійні бар’єри в
tests/parity-routes-v1133.test.mjs: фейковий батьківський скрипт тепер видає реальну форму виводуcompanies(початкова заготовка дзеркалила неправильну формуcandidates— саме тому баг і потрапив у реліз із зеленими тестами), плюс статичні канарки джерела, щоfunded.jsчитаєres.companies(ніколи неres.candidates) і будує рядки таблиці з дочірніми елементами-масивом (+1 → 2144).
[1.133.0] — 2026-08-01
Додано
- Виявлення профінансованих компаній (
#/funded, паритет із батьком #2117) — новий тільки-для-читання вигляд, що ретранслює батьківськийcompany-funded.mjscareer-ops черезGET /api/company-funded: список нещодавно профінансованих компаній «спершу на перегляд», знайдених у публічних стрічках про фінансування з прив’язкою до хоста (TechCrunch, PR Newswire, The Guardian, Hacker News). Ретрансляція запускає скрипт з--json --dry-run(JSON у stdout, без запису файлів), ніколи не передає користувацький ввід у--sources, має обмеження частоти запитів і запускається лише користувачем (кнопка «Знайти», ніколи при монтуванні). Новий модуль маршрутуserver/lib/routes/funded.mjs+public/js/views/funded.js, у розділі «Пошук». - Щотижневий дайджест співбесід (
#/interview-digest, паритет із батьком #2129/#2130) — новий тільки-для-читання вигляд, що ретранслює батьківськийweekly-digest.mjs(без ШІ) черезGET /api/interview/weekly-digest: механічне зведення нотаток сесій співбесід — з якими компаніями та на яких раундах ви проходили співбесіди цього тижня, повторювані компетенції та відкриті прогалини за принципом «найкраще зусилля». Необов’язковий діапазон?from=&to=передається, лише якщо ОБИДВА параметри — валідніYYYY-MM-DD; порожній діапазон — це коректний дайджестavailable:true. Додано доserver/lib/routes/interview.mjs+public/js/views/interview-digest.js, у розділі «Аналітика». - Обидві ретрансляції дотримуються усталеного контракту fail-soft
available:false, коли батьківський скрипт відсутній (CI, автономні інсталяції). 26 нових i18n-ключів ×17 локалей; CI-ізольований набірtests/parity-routes-v1133.test.mjs(+5 → 2143).
Примітки
- Батьківський career-ops просунувся далі за v1.24.0 зі сторінкою «Follow-up Tracker» застосунку Next.js
web/(#1422) та бекенд-рендером PDF (#2182) — не портовано: web-ui вже має власну ретрансляцію нагадувань і власні PDF-раннери, а посиленняfollowup-cadence.mjsнадходить безкоштовно через shell-out ретрансляцію. Зміниset-status.mjs/tracker-utils.mjs— внутрішні для CLI і не дзеркалюються.
[1.132.0] — 2026-07-31
Змінено
- Підсистему рендерингу результатів
#/scanвинесено вpublic/js/lib/scan-results.js(борг за контрактом розміру файлу —public/js/views/scan.jsрозрісся приблизно до ~1254 рядків). Підсистема (renderResults,buildChipRow,getRows, конструктори рядків/фасетів, малювальники опцій і дзеркало реєструFALLBACK_SOURCES) перенесена у фабрикуwindow.ScanResults.create(ctx), що замикається на об’єкт контексту, який надає вигляд. Без зміни поведінки — функції перенесено дослівно, змінні замикання переприв’язано доctx.*;scan.jsтепер має ~906 рядків (другий прохід виділення до цілі в 800 рядків заплановано). - Тести, що читають вихідний код статично, тепер читають обидва файли через
tests/helpers/scan-src.mjs::loadScanSrc();tests/scan-fallback-sources.test.mjsтепер читає дзеркало реєстру зscan-results.js. - Новий регресійний бар’єр у браузері —
tests/playwright-scan-filters.mjsзасіває заготовленийdata/last-scan.jsonі проганяє кожен фільтр#/scan, перевіряючи точну кількість рядків (npm run test:e2e:browser); для цього додано стабільні ідентифікатори фільтрів (#scan-filter-*,#scan-apply). - Банер «Останній реліз» у README скорочено до однорядкового підсумку + посилання на повний журнал змін (довгу багатоверсійну стіну опису прибрано). Застосовано в усіх 17 локалях.
[1.131.2] — 2026-07-31
Змінено
- Поділ
app.cssна три впорядковані таблиці стилів (борг за контрактом розміру файлу — єдиний файл розрісся приблизно до 1990 рядків, значно перевищивши жорсткий ліміт у 800 рядків). Тепер цеapp.css(~672 — a11y, дизайн-токени/тема, бічна панель, основний контент, кнопки, оболонка вмісту),components.css(~595 — картки, сітки, пагінатор, бейджі, таблиці, форми, лог/консоль, markdown, перемикач мов, фільтр-чіпи, банер з’єднання) іoverlays.css(~737 — тост, шухляда сповіщень, модальне вікно, різне/адаптивність, дзеркало[dir="rtl"], docs-fab, usage-hud) — кожен у межах жорсткого ліміту.- Розріз суцільний і в тому ж порядку, тож каскад побайтово ідентичний файлу до поділу;
index.htmlзавантажує всі три як впорядковані<link>. Без зміни поведінки, розмітки чи i18n. - Тести, що перевіряють CSS, тепер читають конкатенацію через спільний хелпер
tests/helpers/css.mjs::loadAppCss(). Новийtests/css-modularization.test.mjsфіксує поділ (файли існують · кожен ≤ 800 рядків · порядок<link>в index.html) → набір 2138. Перевірено в браузері: усі три таблиці стилів парсяться і їхні правила застосовуються.
- Розріз суцільний і в тому ж порядку, тож каскад побайтово ідентичний файлу до поділу;
[1.131.1] — 2026-07-31
Виправлено
- Узгодженість прив’язки хоста в адаптерах для двох джерел v1.130.0 (доопрацювання за код-рев’ю, багаторівневий захист; без зміни поведінки для коректних вхідних даних):
- Адаптер
a16z-speedrun-talentтепер повторно перевіряє перевизначенняapi:/a16z-speedrun-talent:уbuildEndpoint(HTTPS + точний хостspeedrun-talent-network.com) і в разі невдачі відкочується до канонічної стрічки — паритет з адаптеромcryptocurrencyjobs, тож значення з іншим хостом ніколи не потрапляє у слот запиту (раніше це покладалося виключно на перевіркуassertSpeedrunUrlпід час запиту). Перевірка точного хоста тепер — єдиний експортованийSPEEDRUN_TALENT_HOST_RE, спільний для перевірки й адаптера. - Парсер
cryptocurrencyjobs—cleanUrlтепер використовує ту саму перевірку точної відповідності хоста, що йassertCryptocurrencyJobsUrlта перевизначення адаптера (булоendsWith, яке приймало субдомени). Парсер ніколи не є поблажливішим за SSRF-перевірку: посилання елементаsub.cryptocurrencyjobs.coвідкидається. - +2 тести → 2135.
- Адаптер
[1.131.0] — 2026-07-31
Додано
- Дошка стадій-вкладок CRM
#/tracker(портовано з вигляду/pipelineбатьківського веб-застосунку). Панель чіпів воронки трекера + випадний список статусу замінено на смугу вкладок стадій: вкладка Усі плюс по одній вкладці на кожен канонічний статус — Evaluated · Applied · Responded · Interview · Offer · Rejected · Discarded · SKIP · Hired — кожна показує живий лічильник за всю історію, включно зі стадіями з нульовим лічильником, тож уся воронка завжди видима (вигляд CRM). Активна вкладка керує фільтром; повторний клік на неї скидає назад до «Усі». Рядки зберігають тональність оцінки, легітимність, можливості PDF і звіту, а комірка компанії тепер показує бренд-логотип, коли логотипи увімкнено (вимкнено за замовчуванням → без додаткових запитів).- Новий тільки-для-читання маршрут
GET /api/tracker/stagesповертає канонічну воронку (мітки за порядком) + карту згортання псевдонімів, отримані зserver/lib/states.mjs(templates/states.yml, із вбудованим фолбеком) — тож клієнт ніколи не хардкодить whitelist статусів. Застаріла відповідьGET /api/trackerбез параметрів лишається незмінною (лише{ rows }). - Нова чиста, покрита юніт-тестами клієнтська бібліотека
public/js/lib/tracker-stages.jsрозкладає рядки за стадіями сервера, толеруючи випадковий markdown bold і локалізовані псевдоніми (наприклад,aplicado→Applied). Вкладки доступні (role tablist/tab, aria-selected, зона кліку ≥44 px, лічильники в доступному імені кожної вкладки). Нових i18n-ключів немає. Набір тестів 2133.
- Новий тільки-для-читання маршрут
[1.130.0] — 2026-07-31
Додано
- Два нові джерела сканування, портовані з батьківського career-ops v1.24.0 (in-process, без нових залежностей; обидва з’являються у фільтрі джерел
#/scanі на лендінгу cvstart.org):- a16z Speedrun (
a16z-speedrun-talent, #2231) — стрічка JSON усього борду talent-network a16z Speedrun. Прив’язана до хостаspeedrun-talent-network.com, лише HTTPS, 0-індексована пагінація з обмеженням сторінок, наскрізне передаванняq/конфігурації по компанії, fail-soft. - Cryptocurrency Jobs (
cryptocurrencyjobs) — дошка вакансій Web3cryptocurrencyjobs.co, отримується через публічну стрічку RSS 2.0 (без авторизації). Дворазове декодування XML-сутностей, лише віддалені вакансії, роботодавець розбирається з хвоста заголовка"… at <Company>". - Загальна кількість у реєстрі тепер 72 джерела = 67 англомовних + 5 російськомовних (
ALL_ADAPTERS= 67 англомовних адаптерів порталів).
- a16z Speedrun (
Виправлено
echojobs— гібридні ролі лишаються відмінними від віддалених (віддзеркалює батьківський #2258). Регістронезалежний маркерhybridтепер дає"<Місто> · Гібрид"(або простоГібрид, якщо міста немає) іworkplaceType: 'Hybrid', замість згортання вRemote.radancy— застаріла розмітка TalentBrew + транспорт JSON-фрагмента результатів (віддзеркалює батьківський a3e6df9), під контролем ін’єктованогоopts.fetchJson.
Примітки
- Не портовано — CLI-специфічні можливості батька. Великий CLI/режимний шар career-ops v1.24.0 лишається поза web-ui, який є переглядачем + тонким наскрізним записом, а не хостом режимів: таблиці комплаєнсу/юрисдикції, телефонна книга контактів + vCard, транскрипт-дебриф інтерв’ю / визначення платформи дзвінків, встановлення статусу в реєстрі, запис результату, двопрохідний трайдж, jd-подібність, версійована схема артефакту CV заявки, виявлення Playwright-MCP у doctor та
portals/fix-slugs.mjs. Зміни оркестрації сканування, що живуть у батьківськомуscan.mjs— сканер Interamt.de на Playwright, повне сканування iCIMS зворотним ATS, фільтр віддаленості за прийнятністю країни, темп DNS-пошуку, дедуп StepStonerltrі нормалізована колонка компанії в історії сканування — не застосовуються: web-ui запускає сканери EN/RU in-process і не викликаєscan.mjs. - Вже покрито. Фікс згортання діакритики в
role-matcher(#2209) було портовано в v1.127.0, тож тут це no-op.
[1.129.1] — 2026-07-29
Виправлено
- Доопрацювання за AI-рев’ю портів web з v1.128/v1.129 (усі дорадчі, виправлено в корені): порядок рівня в
job-facets.js(явний модифікатор тепер перемагає управлінське слово —Senior Engineering Manager→senior, булоlead); fallback уstates.mjsбільше не пінниться (успішне читання мемоїзується, fallback повертається без кешу — тимчасово недоступний батько на старті перечитується наступним викликом) +console.warnза присутнього, але пошкодженого файлу;score-tone.js— рядок без оцінки нейтральний (muted), не червоний;domainFromName()пропускає не-ASCII slug до/api/logo; +sanity-гард ізоляції вtests/states.test.mjs. +4 тести → 2073.
[1.129.0] — 2026-07-29
Додано
- Фасет «Рівень» + колонка «Свіжість» у
#/scan— бібліотекаjob-facets.jsз v1.128.0 тепер вплетена в UI сканування (раніше лише логіка). Новий дропдаун Рівень розкладає заголовок кожної вакансії на lead/staff/senior/mid/junior/intern (JobFacets.seniorityFromTitle) і автозаповнюється тим, що реально є в результатах (як фасет «Країна»); заголовки без слова-рівня завжди проходять. Зберігається у збережених пошуках, Скиданні та Застосувати. У таблиці з’являються колонка Рівень (бейдж) і zero-token колонка Свіжість (сьогодні/Nдн, зJobFacets.daysSince). 12 i18n-ключів ×17, +3 тести → 2069.
[1.128.0] — 2026-07-29
Додано
- Чотири рішення, портовані з власного веб-застосунку батька (
../web/, Next.js) — переписані на ванільному JS/ESM, без нових залежностей: (1)server/lib/states.mjsчитаєtemplates/states.ymlнаживо як канонічний словник статусів трекера (з CI-fallback) — усуває ручний ре-синк whitelist щорелізу; POST згортає аліаси (іспанські/legacy) до канонічної мітки, funnel у GET групує за канонічним статусом; (2) логотипи компаній у ATS-хостованих рядках черезdomainFromName()(~90 бренд→домен); (3)score-tone.js— 4-рівневий тон оцінки (≥4.2/3.8/3.0 + літерний fallback); (4)job-facets.js— фасети seniority/source/days. +21 тест.
Примітки
- Не портовано (лише концепт): агентський шар дій батька (
actions/registry.ts+api/assistant/route.ts) — креслення на випадок, колиdocs-fabстане копайлотом. Нових джерел немає (реєстр 70), змін i18n/help немає.
[1.127.0] — 2026-07-29
Додано
- Три нові джерела сканування (паритет career-ops v1.23.0) — у реєстрі тепер 70 адаптерів (65 EN + 5 RU): Flowxtra (глобальний агрегатор без авторизації), VDAB (keyword-API фламандської служби зайнятості) та iCIMS (портали
careers-<tenant>.icims.com, окремо відjibeapply). Крім того Cursor повертається до ростера CLI (parent #2115):cli-detectтепер виявляєcursor(10 інструментів), ростер відновлено в help/README/config ×17.
Виправлено
- agenticjobs переведено зі скрейпінгу HTML на REST API (#2167); Greenhouse відновлює місто з
/offices, колиlocation.name— лише модель роботи (#2104); паритет role-matcher (#1933/#2164/#2009: префікс MTS, базовийproduct, згортання акцентів, незгода sub-baseline).
Примітки
- Не портовано. Більшість v1.23.0 — CLI/dashboard-поверхня, яку web-ui не викликає (batch-tailor, discover-ats, режими NL/PT, теми PDF, Go-дашборд, updater/doctor); релейні скрипти без змін. VERSION батька → 1.23.0.
[1.126.1] — 2026-07-25
Виправлено
- Дві точки дрейфу ростера CLI, які пропустив ресинк v1.126.0 — (1) інтро вкладки API keys у
#/config(config.providerModelNote, i18n ×17) перелічувало лише 7 CLI — тепер Antigravity і Grok Build вставлені після OpenCode; (2) другий рядок порівняльної таблиці в довідці (×17) і зібраний у CI help сайту все ще містилиInside Claude Code / Codex / Cursor / Gemini CLI— застарілий набір із Cursor — тепер повний ростер. Обидва рядки використовували роздільники слеш/середня крапка, які патерни свіпу v1.126.0 не покривали. i18n-снапшот перегенеровано; сьют лишається 1969.
[1.126.0] — 2026-07-25
Додано
- Вкладка інструментів AI CLI тепер виявляє всі 8 першокласних CLI career-ops — ростер
#/configсинхронізовано з батьківськимdocs/SUPPORTED_CLIS.md: уserver/lib/routes/cli-detect.mjsдодано Grok Build CLI (grok) і Kimi CLI (kimi), а Antigravity тепер спершу шукає канонічний бінарникagy. Скан PATH лише-для-читання тепер повідомляє 9 інструментів; знайдений бінарник, як і раніше, ніколи не запускається.
Змінено
- Ресинк документації з career-ops.org/docs — звірив кожну поверхню документації з живими сторінками батька (прочитано всі 31). Канонічний ростер AI-асистентів (help ×17 + README ×17) тепер перелічує 8 першокласних CLI — Claude Code, Codex, OpenCode, Antigravity CLI, Grok Build CLI, Qwen Code, Kimi, GitHub Copilot CLI — плюс Gemini CLI (застаріла обгортка). Help-бандли зберігають структуру 29 H2 / 105 H3.
[1.125.4] — 2026-07-23
Змінено
- залежності site (dependabot #151–#153) —
sharp0.34.5→0.35.3,svgo4.0.1→4.0.2,fast-uri(dev) 3.1.3→3.1.4 уsite/; збірка Astro зелена, SPA/сервер не зачеплені.
Примітки
- Паріті-свіп батьківського проєкту (career-ops
37d17ec..254764a, після v1.22.0) — портувати нічого: guard неправильного рядка вset-status(#2108) — лише CLI (у web-ui рядок трекера обирається явно в UI, і жоден маршрут не викликаєset-status.mjs); Risk Summary локалізованих режимів (#2109) — файлиmodes/<lang>/, які web-ui не читає (лише верхньорівневіmodes/*.md); перевірка маніфестуupdate-system(#2111) — лише апдейтер; решта — документація батька (турецький README, SIGNATURES ×4, SCRIPTS.md, акценти es). VERSION батька лишається 1.22.0 —parentVersionбез змін.
[1.125.3] — 2026-07-23
Виправлено
- LLM-промпти данською та гінді відповідали англійською (повідомив користувач) —
LOCALE_NAMESі всі п’ять наборівSCAFFOLD_STRINGSуserver/lib/prompts.mjsтак і не були розширені дляdaтаhi, тожresolveLocale()відкочувався доen, і кожен AI-промпт — deep research (живий і ручний), режими, оцінювання, інтерв’ю, нетворкінг, CV Studio — втрачав директиву# Output languageу цих двох локалях. Тепер обидві — повноправні: мовна директива + локалізоване обрамлення. Регресійний гейт уtests/locale-scaffold.test.mjsтепер обходить канонічний список із 17 локалей замість захардкоджених 12, а новий структурний гейт валить будь-який ключ обрамлення, що падає в англійську — локаль, яка пропуститьprompts.mjs, більше не вийде (+12 тестів, разом 1969).
[1.125.2] — 2026-07-22
Виправлено
- Deep research через Gemini: HTTP 502 (
MALFORMED_FUNCTION_CALL) (#145, внесок @Alien10140) — живий промпт/api/deepнаказував моделі «Use WebFetch / WebSearch» і зберегти бриф у файл, але безінструментальні API-провайдери не мають каналу інструментів; Gemini відповідав викликом функції замість тексту, що проявлялося як порожній HTTP 502.buildDeepPromptіbundleProjectContextотримали прапорецьheadless: живі запуски (Anthropic/Gemini/каскад резервів) отримують промпт без інструментів, який пише бриф із вбудованого контексту, а copy-paste-промпт для Claude Code зберігає інструкції щодо інструментів. +1 тест уtests/critical-fixes.test.mjs.
Змінено
- Типові моделі Gemini оновлено з застарілої
gemini-2.0-flash(#144, внесок @Alien10140) — випадний список у Конфігурації, серверний резерв уgemini.mjs(що мовчки розходився з підказкою), ланцюжок резервів OpenRouter,config.geminiModelHint×17 та довідка ×17 тепер одностайно вказуютьgemini-3.6-flash. Новий анти-дрейф ґейтtests/gemini-default-model.test.mjs(+5 тестів) фіксує всі поверхні на одному літералі — у сьюті тепер 1957 тестів.
[1.125.1] — 2026-07-21
Виправлено
- SuccessFactors: мультибрендові тенанти RMK зберігають свій шлях бренду (батьківський #2099, після v1.22.0) — холдингові компанії, які ведуть кілька придбаних брендів на одному спільному інстансі RMK, розрізняють їх за сегментом шляху (
careers.nemetschek.com/Bluebeam/проти…/Vectorworks/); адаптер раніше згортав налаштований URL до його origin, непомітно скануючи вакансії батьківського бренду. Тепер ендпоінт зберігає префікс бренду, відкидаючи лише кінцевий сегмент/search/або/tile-search-results/, тож ніщо ніколи не дублюється саме на себе; тенанти з одним доменом лишаються побайтово незмінними. Новий експортований хелперresolveTenantBase+ 1 перенесений тестовий блок уtests/sources-successfactors.test.mjs.
[1.125.0] — 2026-07-21
Додано
- cvstart.org: розділ лендінгу «Джерела вакансій» — новий розділ між скриншотами та порівнянням, який перелічує всі 67 джерел сканування у вигляді клікабельних чіпів (62 англомовні дошки/ATS + 5 російських дощок під власним підзаголовком), кожне з яких веде на публічний сайт джерела. Список синхронізується з живим реєстром адаптерів під час збірки (
sync-assets.mjs→facts.sources), тож він ніколи не може розійтися із застосунком; курований довідник посилань уSources.astroзахищений новим тестомtests/site-sources.test.mjs. У навігації шапки з’явився якір Sources; додано 4 нові ключі i18n сайту ×17. Також виправлено списокinLanguageу JSON-LD лендінгу, в якому досі бракувалоhi.
[1.124.0] — 2026-07-21
Додано
- П’ять джерел сканування (паритет із батьківським v1.22.0, #1808/#1572/#2024/#2055) — Welcome to the Jungle (JSON API для всієї дошки), Agentic Engineering Jobs (дошка агентного/AI-інжинірингу), Jobvite (ATS на тенант без автентифікації), Gem (ATS на тенант) і Alibaba Group (JSON API кар’єрної сторінки, шаблон Meituan/Tencent). Кожне джерело — прив’язана до хоста, CI-ізольована пара джерело + адаптер; реєстр тепер постачається з 67 адаптерами (62 англомовних + 5 російськомовних); резервний список випадаючого списку Source на
#/scanта його дрейф-гейт оновлено; п’ять нових наборів тестівtests/sources-{wttj,agenticjobs,jobvite,gem,alibaba}.test.mjs.
Виправлено
- Arbeitsagentur: загальнонаціональна віддалена робота лише коли
homeofficetypдорівнюєVOLLSTAENDIG(батьківський #1981) — запитhomeoffice=nv_trueтакож повертає гібридні вакансії, тож перевірка на віддаленість тепер підтверджує кожен збіг через ендпоінт деталей вакансії невеликими партіями і безвідмовно закривається (помилка пошуку зберігає справжнє місто вакансії, тож фільтри локації все одно застосовуються). - SmartRecruiters: публічні URL вакансій формувалися без
/postings/(батьківський #2047) — посилання тепер ведуть на публічну сторінку вакансії замість 404 для тенантів, чий публічний сайт відкидає цей сегмент.
Примітки
- Батьківський v1.22.0 також містив зміни на боці CLI, у які веб-інтерфейс не заходить через shell або які вже покриває: шаблон CV zh-CN + типографіка PDF, режим
/expand, налаштування кешування промптів провайдерів (Gemini/OpenAI/Ollama), розбивка токенів за кроками (у веб-інтерфейсі є власний лічильник використання), серіалізація блокування запису трекера (веб-інтерфейс скеровує записи черезwithFileLockще з v1.21), прапорці CLIvisa_filterта абсолютної дати публікації для сканування (у веб-інтерфейсі є власний фільтр віку «Опубліковано протягом») та посів дедуплікації відомих джерел (сканер веб-інтерфейсу веде власну дедуплікацію історії сканування).
[1.123.0] — 2026-07-17
Додано
- Джерело сканування Oracle Recruiting Cloud (паритет із батьківським v1.21.0, #1929) — REST API
recruitingCEJobRequisitionsбез автентифікації для кар’єрних сайтів Oracle Fusion/ORC (JPMorgan Chase, Oracle, BNY Mellon, American Express, Honeywell, …): прив’язка до хоста*.fa[.<region>][.ocs].oraclecloud.com, номер сайту визначається зcareers_urlкожної відстежуваної компанії, пагінація за зсувом із жорсткою межею кількості сторінок і WAF-обізнані заголовки на кшталт браузерних. Реєстр тепер постачається з 62 адаптерами (57 англомовних + 5 російськомовних); резервний список випадаючого списку Source на#/scanта його дрейф-гейт оновлено; новий CI-ізольований набір тестівtests/sources-oraclecloud.test.mjs.
Виправлено
- Детектор репостів: базові назви залишаються окремо від сиблінгів зі спеціалізованим суфіксом (батьківський #1922) — «Senior Analytics Engineer» більше не групується із «Senior Analytics Engineer, People Analytics»: якщо токени однієї назви є строгою підмножиною токенів іншої, а додатковий токен є справжньою спеціалізацією (а не базовим словом), обидві вакансії вважаються окремими відкритими позиціями. Позначки репосту («(Repost)», «relisted») тепер трактуються як стоп-слова інформаційного шуму. +2 перевірки в
tests/detect-reposts.test.mjs.
Примітки
- Батьківський v1.21.0 також містив зміни на боці CLI, у які веб-інтерфейс не заходить через shell або які вже покриває: попередження про повторну подачу заявки до тієї самої компанії (у веб-інтерфейсі є пауза для повторної подачі ще з v1.84.0), прапорці
--format/--reportсупровідного листа, режими промпту співбесіди для red-flag / панельної розвідки / no-show листа, персистентність довіри до джерел сканування та здоров’я порталів (веб-інтерфейс запускає власний внутрішньопроцесний сканер ізtrust-validatorі сторінкою здоров’я порталів) і розширення статистики/розриву в зарплаті (транслюються лише для читання та безвідмовно).
[1.122.0] — 2026-07-16
Додано
- Гінді (हिन्दी) — 17-та мова — повний словник інтерфейсу (~1 110 ключів), повний вбудований посібник довідки (паритет 29 H2 / 105 H3),
README.hi.md, новийCHANGELOG.hi.md(починається з v1.122.0, за прецедентом de/it/tr), лендинг cvstart.org + сторінки Методологія/Ліцензія/Журнал змін/Довідка, перемикач мов (🇮🇳), автовизначення мови браузера та локалізований знімок дашборда. Кожен гейт паритету ×16 тепер працює ×17: паритет словника i18n + знімок, гейти H2/H3 довідки, паритет CHANGELOG,check-i18nсайту та перевірка локалей Playwright.
[1.121.0] — 2026-07-16
Додано
- Сторінки Methodology, License і Changelog на cvstart.org — лендинг отримав три нові розділи всіма 16 мовами, поруч із наявним блоком Порівняння: /methodology/ (шкала оцінювання за шістьма вимірами 0.0–5.0, поріг подання заявки 4.0 і правила «ніколи не робимо» — локалізований стислий виклад career-ops.org/methodology), /license/ (канонічний текст ліцензії MIT із посиланням на NOTICE.md) і /changelog/ (цей файл, відображений для кожної локалі з 16 перекладених CHANGELOG репозиторію). Новий пункт Methodology у шапці та посилання в блоці ресурсів футера;
sync-assets.mjsтепер синхронізує CHANGELOG ×16 та LICENSE у білд сайту, тож сторінки більше не можуть розійтися з репозиторієм. - Посилання на методологію в документації — README (усіма 16 мовами), канонічний список §1 вбудованого посібника довідки (усіма 16 мовами) та вікі тепер посилаються на career-ops.org/methodology (а також FAQ і глосарій) поруч із наявними посібниками career-ops.org/docs.
Змінено
- Оновлено банер релізу та бейджі в README (1850 тестів, реліз v1.121.0) — банер досі анонсував v1.119.5.
[1.120.0] — 2026-07-16
Додано
- Маніфест CareerOps (паритет із батьком v1.20.0) — батьківський проєкт випустив Маніфест CareerOps (
MANIFESTO.md· career-ops.org/manifesto) і тепер показує його у своєму README, апдейтері та Go-дашборді. Веб-інтерфейс наслідує це: нове посилання у футері бічної панелі відкриває сторінку маніфесту (новий ключ i18nfooter.manifestoу всіх 16 локалях), вбудований посібник довідки отримав §29 «Маніфест CareerOps» усіма 16 мовами, README пояснює, що таке маніфест і як його підписати, а футер лендингу cvstart.org теж посилається на нього.
Примітки
- Батько v1.20.0 також виправив придушення відомих навичок у цільовому режимі
upskill, приглушив dotenv, щоб stdoutscan --jsonзалишався придатним для парсингу, і виправив HTML-шаблон CV, щоб заголовок ролі не відривався від своїх пунктів — це поверхні на боці CLI, у які веб-інтерфейс не заходить через shell; змін коду веб-інтерфейсу не знадобилося.
[1.119.5] — 2026-07-13
Виправлено
- Кнопка мови на лендінгу більше не переноситься — після появи прапорів у v1.119.2 підпис перемикача в шапці (наприклад «🇷🇺 Русский») міг розбиватися до трьох рядків на вузьких десктопних ширинах; підпис перемикача та всі пункти випадного списку тепер
whitespace-nowrap— прапор + ендонім завжди в один рядок. Список мов у футері переведено з жорсткої двоколонкової сітки на рядок однорядкових пунктів із переносом — «🇧🇷 Português (Brasil)» теж більше не рветься посеред назви.
[1.119.4] — 2026-07-13
Змінено
- LICENSE називає автора — рядок копірайту тепер: Sergei Emelianov (Fighter90) https://sergey-cv.com and career-ops-ui contributors (канонічний текст MIT не змінено). Новий NOTICE.md детально розписує ліцензування: хто власник копірайту, що саме покриває грант MIT (код, доки, переклади, лендінг, вікі), чого НЕ покриває (ваші дані в рантаймі, батьківський проєкт, контент джоб-бордів, торговельні марки), таблицю сторонніх компонентів (express/js-yaml — MIT; Astro/Tailwind — MIT; шрифти Figtree та JetBrains Mono — SIL OFL 1.1; sharp — Apache-2.0) і необов’язковий рядок атрибуції.
[1.119.3] — 2026-07-13
Додано
- SECURITY.md — політика безпеки, на яку посилався CONTRIBUTING, тепер існує: підтримувані версії, приватний процес репортів (у репозиторії ввімкнено private vulnerability reporting GitHub — вкладка Security → «Report a vulnerability»), модель загроз для localhost-застосунку одного користувача (у скоупі: XSS через ворожі вакансії / SSRF / path traversal / витоки секретів / послаблення CSP; поза скоупом: DoS власного localhost і проблеми батьківського проєкту) та базова лінія хардинінгу для рев’юерів.
[1.119.2] — 2026-07-13
Додано
- CONTRIBUTING.md — гід контриб’ютора, на який лендінг і README посилалися весь цей час, тепер існує: встановлення, карта проєкту, жорсткі правила безпеки/no-build, рівні тестування, walkthrough «двох реєстрів» для додавання скан-джерела, контракт i18n ×16, конвенції комітів/PR і процес релізу.
- Прапори мов на лендінгу — перемикач мов cvstart.org, сітка мов у футері та банер «читайте своєю мовою» тепер показують прапор кожної локалі поруч з її ендонімом (той самий набір регіональних індикаторів, що й у мовному
<select>застосунку; деградує до літер регіону там, де немає гліфів прапорів). - Правки футера лендінгу — неробоче посилання Discussions (функцію не ввімкнено в репозиторії) тепер веде на вікі проєкту, а у футері вказано автора: Sergei Emelianov (sergey-cv.com · LinkedIn).
[1.119.1] — 2026-07-13
Виправлено
- Фільтр джерел на
#/scanназдогнав реєстр — статичний списокFALLBACK_SOURCESза випадним списком Source (використовується лише колиGET /api/scan/sourcesнедоступний) мовчки відставав із v1.87.0: в офлайн-фолбеку бракувало 20 провайдерів (Amazon, Avature, SAP SuccessFactors, Get on Board, Dassault Systèmes, beesite, HigherEdJobs, JibeApply (iCIMS), softgarden, Cornerstone, Phenom, Radancy, Deutsche Bahn, EchoJobs, TKMS, Heckler & Koch, Rheinmetall, LaraJobs і нові Meituan / Tencent). Синхронізовано з усіма 61 і тепер закрито дрейф-тестом, що валить CI при розходженні клієнтського списку з серверним реєстром (значення І лейбли). +1 тест (1845).
[1.119.0] — 2026-07-13
Паритет із батьківським career-ops v1.19.0 + оновлення лендінгу cvstart.org.
Додано
- 2 нові сканер-провайдери — Meituan (
zhaopin.meituan.com) і Tencent (careers.tencent.com): публічні JSON-API китайських тех-дощок без авторизації, визначаються за хостом або явнимprovider:, серверний пошук за ключовими словами з пагінацією та дедуплікацією за URL — тепер 61 адаптер (56 EN + 5 RU). +20 тестів (1844). - Блок контриб’юторів на лендінгу — cvstart.org показує аватари всіх, хто долучився кодом (GitHub API
/contributorsна етапі збірки, боти відфільтровані), локалізовано всіма 16 мовами, з посиланням на повний граф контриб’юторів. - Живий лічильник зірок GitHub на лендінгу — бейдж у шапці тепер оновлюється на клієнті з GitHub API при кожному візиті (знімок збірки — як fallback), а щотижнева перезбірка Pages за розкладом не дає застаріти знімку та списку контриб’юторів; API-виклики в CI автентифіковані токеном.
Виправлено
- Запити Workday CXS несуть браузерні заголовки (батьківський #1813) — тенанти за Cloudflare (спостерігалося наживо: geico) відповідають 500 на запити без звичайних UA/
accept-language/origin/referer; фетчер тепер виводить origin і слаг сайту з самого CXS-URL. Запити Glints отримали той самий браузерний UA + origin/referer — обидва з спільної константиBROWSER_LIKE_USER_AGENTвhttp-json.mjs.
[1.118.4] — 2026-07-10
Виправлено
- Скан hh.ru давав 0 вакансій з російського IP (посилання на регіональному піддомені) — з російського резидентного IP hh.ru редиректить пошук на регіональний піддомен (
sochi.hh.ru,spb.hh.ru, …) і віддає посилання на вакансії на цьому піддомені. Парсер шукав посилання заголовка за жорстким хостомhttps://hh.ru/vacancy/і не знаходив жодного регіонального — цілком робочий скан мовчки записував 0. Тепер приймається будь-який хост*.hh.ru(рекламаadsrv.hh.ru/click?…так само відсікається — у неї немає шляху/vacancy/<id>), а URL результату канонізується вhttps://hh.ru/vacancy/<id>. Перевірено наживо: 17 реальних вакансій парсяться зі сторінкиsochi.hh.ru, де раніше було 0. +1 тест (1824).
[1.118.3] — 2026-07-10
Виправлено
- hh.ru мовчки повертав 0 вакансій (заглушка VPN-перевірки) — hh.ru тепер відповідає 302-редиректом на заглушку
/vpncheeck(«VPN мешает работе сайта») мережам, які вважає VPN/проксі (датацентрові IP); заглушка віддає HTTP 200 без жодної картки вакансії, тож скан звітував 0 без помилки. Сканер тепер розпізнає редирект за фінальним URL відповіді, вимикає hh.ru до кінця прогону й пише чесну підказку: трафік має справді виходити через резидентний IP — системний VPN/проксі може лишатися ввімкненим, навіть коли перемикач у браузері вимкнено. +1 тест (1823).
[1.118.2] — 2026-07-10
Обслуговування
- Доопрацювання лендінгу (#118) —
site/README.mdприведено до Astro 7 (security-апгрейд з #116), прибрано невикористаний імпорт, додано 4 виконувані гарди для білд-скриптів лендінгу: гейт i18n-паритету доказово падає на зламаному словнику, аsync-assetsніколи не пише позаsite/— набір 1822. Розібрано два алерти CodeQL (один виправлено в коді, один відхилено як навмисну поведінку білда).
[1.118.1] — 2026-07-10
Виправлено
- Сканування hh.ru з-поза меж Росії — hh.ru тепер віддає HTTP 451 (регіональне юридичне блокування) неросійським IP на публічних сторінках пошуку. Сканер обробляє 451 як 403: після першого блокування hh.ru вимикається до кінця прогону з чесним рядком у лозі про російську IP / VPN-вихід, тож решта запитів та інші RU-джерела не витрачаються марно. Довідку §7 оновлено всіма 16 мовами. +1 тест (1818).
[1.118.0] — 2026-07-09
Пакет паритету з батьківським career-ops v1.18.0.
Додано
- 9 нових сканер-провайдерів — Cornerstone OnDemand (
csod), Phenom (phenom), Radancy (radancy), Deutsche Bahn (deutschebahn), EchoJobs (echojobs), TKMS (tkms), Heckler & Koch (hecklerkoch), Rheinmetall (rheinmetall), LaraJobs (larajobs) — тепер 54 адаптери. Адаптер Lever додатково розпізнає дошки EU-тенанта (jobs.eu.lever.co). - Статус
Hiredу трекері (паритет зіstates.ymlбатька): прийняті офери отримують власний канонічний статус, святковий бейдж і банер «роботу знайдено» на#/tracker; воронка та конверсії рахують його як такий, що пройшов усі етапи. - Вкладка «За весь час» у
#/stats— ретрансляція лише для читання батьківськогоstats.mjs(зведення трекера за весь час, накопичені частки воронки, підсумки сканера, покриття порталів) плюс спостереження щодо компенсації зsalary-gap.mjs(бажана vs заявлена vs фактична, за кожною заявкою). Нові маршрутиGET /api/stats/lifetimeіGET /api/stats/salary-gap— shell-out з нульовою вартістю токенів, м’яка деградація{available:false}без батьківського проєкту. - 28 нових i18n-ключів у всіх 16 локалях; довідку §14/§26 оновлено всіма мовами.
Тести
- +38 юніт-тестів (три сьюти паритету провайдерів + маршрути релея/статусу) — разом 1817.
[1.117.2] — 2026-07-06
Фікс порожнього трекера для shell-out паритету. Батьківські скрипти виходять із кодом 1 і структурованим {error}-JSON, коли в трекері ще немає заявок; дошка фоллоу-апів і вкладка патернів показували це як «script-error». Обидва маршрути тепер передають це як здоровий порожній стан (available:true, empty:true), і UI показує чесне «поки порожньо». Перевірено наживо на реальному батькові.
Нове: немає.
[1.117.1] — 2026-07-06
Доналаштування v1.117.0 (розбір CodeQL). Три shell-out ендпоінти (GET /api/followup, POST /api/followup/seed, GET /api/stats/patterns) тепер несуть спільний per-IP лімітер (кожен запит породжує дочірній процес; на loopback — no-op). Витяг тексту за URL у «Додати в CV» вичищає теги до нерухомої точки й потім видаляє всі залишкові </> — доказово повне очищення для тексту LLM-промпту. Поведінка на коректному вводі незмінна.
Нове: немає.
[1.117.0] — 2026-07-06
Пакет паритету з батьком — шість можливостей батьківського career-ops тепер в UI. (1) Дошка каденції на #/followup: терміновість за кожною заявкою (🔴/🟠/🟡/🔵) з followup-cadence.mjs, плюс кнопка «Проставити дати» (followup-seed.mjs --backfill). (2) Патерни відмов: четверта вкладка Статистики запускає analyze-patterns.mjs (лише читання) — розподіл результатів, рекомендації, частка просування за ATS-вендорами. (3) Додати в CV: картка CV Studio перетворює URL чи вставлений текст на ATS-пункти, засновані ЛИШЕ на цьому джерелі (лише пропозиції, без записів; завантаження URL захищене від SSRF). (4) 4 нові сканер-провайдери — beesite, HigherEdJobs (RSS), JibeApply (iCIMS), softgarden — реєстр тепер налічує 50 адаптерів (45 EN + 5 RU), усі в списку Scan. (5) Крок передперевірки нокаут-питань у чек-листі Apply. (6) Раннер reconcile (/api/run/reconcile). Shell-out-маршрути чесно деградують без батьківських скриптів.
- Новий модуль
server/lib/routes/followup.mjs(31-й) + нові маршрути + 8 файлів source/adapter. Тести: 6 + 7 нових; сьют 1737 → 1750. 41 новий ключ i18n ×16. Довідка §13/§17/§24/§26 розширена ×16.
Нове: GET /api/followup, POST /api/followup/seed, GET /api/stats/patterns, POST /api/cv-studio/add-entry, POST /api/run/reconcile.
[1.116.0] — 2026-07-06
Перероблено лічильник витрат + перший наскрізний тест віджетів. Лічильник витрат ШІ (v1.114.0) виправлено й правильно закріплено: тепер він прикріплений унизу лівої бічної панелі (на всю ширину, та сама поверхня) й резервує внизу місце, що дорівнює його висоті, аби меню ніколи не перекривалося — навігація та підвал версії завжди прокручуються вільно над ним. Він оновлюється наживо (кожні 15 с, при фокусі вкладки та зміні маршруту), а кожен рядок вікна тепер показує реальні <токени> · <оцінка вартості> (смуги масштабуються відносно 30-денного вікна) замість завжди-100% «частки». Крім того: стійкий бар’єр typeof в імпортері CV закриває в першопричині повторюваний хибнопозитивний type-confusion CodeQL, а новий наскрізний тест Playwright проганяє обидва постійні віджети в реальному браузері.
public/js/lib/usage-hud.js+app.css,server/lib/cv-import.mjs. Тести:tests/playwright-widgets.mjs(2 E2E) +tests/usage-hud.test.mjs(10). Довідка §6 розширена ×16.
Нове: немає.
[1.115.0] — 2026-07-06
Шліфування дизайну (консервативне, кораловий бренд збережено). Легкий прохід удосконалення спільної дизайн-системи — без перебудови, без зміни палітри. Картки метрик на дашборді тепер трохи піднімаються та отримують коралову рамку при наведенні (як плитки швидких дій); картки контенту піднімаються ледь-ледь; кнопки primary / dark / danger отримують тінь у спокої та м’яке підняття при наведенні для глибини; великі числа вирівнюються через tabular-nums; а інтерактивні елементи отримують м’який кораловий ореол за чітким 2px-кільцем клавіатури. Уся анімація поважає prefers-reduced-motion, а ореол обмежено елементами керування — ніколи не глобальний *:focus-visible.
- Лише CSS (
public/css/app.css); без змін розмітки, i18n, маршрутів чи CSP. Тести:tests/design-polish-v1115.test.mjs(5). Перевірено вживу через Playwright.
Нове: немає.
[1.114.0] — 2026-07-06
Лічильник використання та вартості ШІ в бічній панелі (лівий нижній кут). Компактний розділ ВИКОРИСТАННЯ тепер розташований унизу бічної панелі (фіксована картка в лівому нижньому куті, якщо панелі немає; у правому нижньому для RTL) на кожній сторінці. Він показує використання токенів LLM за вікнами 24г / 7д / 30д — кожне як <токени> · <частка%> із зеленою смугою (частка від усього часу) — плюс підвал з оцінкою вартості за 24г. Дані — доступний лише для читання звід GET /api/usage із data/llm-usage.jsonl (лише локально), те саме джерело, що й сторінка #/usage; вартість оцінна, а запуски в ручному режимі безкоштовні й не враховуються. Згортається — заголовок перемикає, стан зберігається.
- Новий клієнтський віджет
public/js/lib/usage-hud.js, завантажується зindex.html, монтується в бічну панель над підвалом версії (запасний варіант — фіксований кут). Безпечний для CSP; з урахуванням теми та дзеркалом RTL. Без нового маршруту сервера. Тести:tests/usage-hud.test.mjs(8). 3 нові ключі i18n ×16.
Нове: немає.
[1.113.0] — 2026-07-06
Плаваючий помічник «Запитати довідку» на кожній сторінці. Градієнтна кнопка-робот із чатом тепер плаває в правому нижньому куті (у лівому нижньому для RTL) кожної сторінки. Натисніть, щоб відкрити компактний чат, який відповідає на питання щодо використання, спираючись ЛИШЕ на вбудовану довідку вашою мовою — той самий ендпоінт, що й сторінка #/docs-assistant (POST /api/docs-assistant/ask), тож він ніколи не читає ваше резюме, профіль чи трекер. Наживо з ключем LLM; без ключа → готовий промпт. У шапці — аватар-робот і статус онлайн; чипи підставляють часті питання; Escape або клік ззовні закриває; на сторінці #/docs-assistant кнопка прихована.
- Новий клієнтський віджет
public/js/lib/docs-fab.js, монтується глобально зindex.html; безпечний для CSP; стилі з урахуванням теми та дзеркалом RTL уapp.css. Без нового маршруту сервера. Тести:tests/docs-fab.test.mjs(8). 6 нових ключів i18n ×16. Довідка §1 розширена на місці.
Нове: немає.
[1.112.0] — 2026-07-06
Консолідація документації та QA. Без видимих користувачу змін коду. Документ угод SDD (docs/sdd/CONVENTIONS.md) оновлено до поточних 30 модулів маршрутів (було 24) та поточної базової лінії тестів; визначальний загальнопроєктний QA-промпт (qa/QA-REGRESSION-PROMPT.md) консолідовано — механіку релізу актуалізовано (v1.111, parentVersion 1.17.0, публікація за подією релізу), таблицю доповнень §14 виправлено («Виключити» в Scan перепозначено як v1.109.0) і доповнено закриттям CodeQL з v1.111 — тож він самодостатній як єдиний регресійний промпт для всієї функціональності. Додано один тест покриття для гілки завеликого завантаження.
Нове: немає.
[1.111.0] — 2026-07-06
Безпека — закриття беклогу CodeQL. Три посилення ешелонованого захисту, що закривають решту зауважень статичного аналізу в першопричині, а не через dismiss. stripDangerousMarkdown тепер екранує < у будь-якому усіченому відкритті небезпечного тега (навантаження, що закінчується на <script/<iframe/…), тож у виводі доказово не лишається живого небезпечного тега. Імпорт CV читає розмір завантаженого буфера через явне приведення Number() — бар’єр проти плутанини типів. Рядки ролі режимів тепер є шаблонними рядками, інтерпольованими через String.replace, а не збереженими функціями, що повністю прибирає виклик динамічної диспетчеризації. Видимої для користувача зміни поведінки немає.
server/lib/security.mjs,server/lib/cv-import.mjs,server/lib/prompts.mjs. Тести:tests/security-hardening-v1111.test.mjs(7) + оновлений тест-страж v1108. Без змін i18n/довідки/маршрутів.
Нове: немає.
[1.110.0] — 2026-07-06
Оновлення документації та QA (усі мови). Без змін коду. Повнопроєктний QA-промпт оновлено до v1.109.0 з новим §14 (v1.98→v1.109), а вічнозелені промпти UX-аудиту та design-export отримали поточний набір екранів. Кожен абзац довідки, доданий у v1.100–v1.109, тепер перекладено всіма 16 мовами.
Нове: немає.
[1.109.0] — 2026-07-06
Фільтр «Виключити» в Scan + огляд пайплайна (паритет з веб-версією). На #/scan поле Пошук тепер трактує коми як АБО («ролі для пошуку»), а нове поле Виключити ховає рядки, де компанія/роль/локація містить будь-яке слово через кому (напр. senior, staff); обидва запам’ятовуються у збережених пошуках. На #/pipeline компактна смуга огляду показує пайплайн з одного погляду — N у вхідних, N відстежується та лічильники Applied / Responded / Interview / Offer з трекера, кожен чип веде до #/tracker.
- Лише клієнт (без нового маршруту/записів).
public/js/views/scan.js+public/js/views/pipeline.js. Тести:tests/scan-pipeline-ui-v1109.test.mjs(2). 4 нові ключі i18n ×16. Довідка §7 + §8 розширені на місці.
Нове: немає.
[1.108.0] — 2026-07-06
Посилення безпеки (розбір CodeQL, раунд 2). Виправлено ще три знахідки низької серйозності: збирач промптів розв’язує рядок ролі локалі за власним ключем + typeof === function, щоб підроблена локаль не могла викликати метод прототипу (unvalidated-dynamic-method-call); slug імені PDF-файлу обмежено 200 символами до регулярки, щоб вхід з самих дефісів не відкочувався (поліноміальний ReDoS); а імпорт документа приводить масивний filename (повторний заголовок) до рядка (type-confusion). Без зміни поведінки для коректного вводу.
server/lib/prompts.mjs,server/lib/routes/runners.mjs,server/lib/cv-import.mjs+tests/security-hardening-v1108.test.mjs(3). За v1.106–v1.108 беклог статичного аналізу скоротився зі 167 до ~14: усі справді значущі для безпеки знахідки виправлено, решту (захищені/санітизовані хибні спрацювання + lint рівня note) відхилено з обґрунтуванням.
Нове: немає.
[1.107.0] — 2026-07-06
Посилення санітайзера (ешелонований захист від XSS у стані спокою). stripDangerousMarkdown — нейтралізує небезпечний HTML у збереженому markdown резюме/вакансії, щоб будь-який споживач, що оминає клієнт з екрануванням-при-рендері, лишався безпечним — тепер виконує видалення тегів до нерухомої точки (повторювати до стабілізації), щоб видалення, що переформовує корисне навантаження (напр. <scr<script></script>ipt>), було впіймано, збігається із закривними тегами script/style тощо зі сміттям у кінці (</script foo>) і видаляє незакритий виконуваний відкривний тег (<script …>). Поведінка для коректного markdown не змінюється — лише видаляє більше.
server/lib/security.mjs: цикл нерухомої точки (обмеження 8 проходів) + шаблони закривних тегів[^>]*>+ видалення незакритого відкривного тега. +3 регресійні випадки вtests/cv-xss-bypasses.test.mjs. Авторитетна межа XSS лишається екрануванням на виводі (UI.md); це посилює гарантію в спокої й закриває відповідні знахідки CodeQL.
Нове: немає.
[1.106.0] — 2026-07-06
Посилення безпеки (розбір CodeQL). Виправлено три реальні (хай і низької серйозності) знахідки після проходу беклогу статичного аналізу: шлях помилки рендера маршруту тепер екранує повідомлення про помилку до потрапляння в DOM (помилка сервера може відобразити введення користувача, тож вважається недовіреною — межа XSS), а записи властивостей профілю/конфігу відхиляють ключі __proto__ / constructor / prototype (захист від забруднення прототипу про всяк випадок — ключі беруться з фіксованих специфікацій полів, а не з сирого введення). Більшість решти попереджень — хибні спрацювання на легітимних читаннях/записах сканера в data/* та на маршрутах, що вже мають власний обмежувач; відхилено з обґрунтуванням.
public/js/router.jsекрануєerr.messageчерезUI.escapeHtmlпередinnerHTML;server/lib/routes/content.mjsіserver/lib/routes/config.mjsзахищають ключі прототипу. Без зміни поведінки для коректного введення. Тести:tests/security-hardening-v1106.test.mjs(3). Нових ключів i18n немає.
Нове: немає.
[1.105.0] — 2026-07-06
Сторінка витрат і вартості ШІ. Нова сторінка Витрати ШІ (бічна панель, поруч зі «Здоров’ям») показує, скільки токенів ви витратили на живі генерації ШІ — оцінки, звіти, чати — з розбивкою за провайдерами за останні 24 години, 7 днів, 30 днів і весь час, з оцінкою вартості в USD. Кожен живий виклик додає невеликий запис {provider, in, out} до data/llm-usage.jsonl (нікуди нічого не надсилається); запуски без ключа (ручний режим) нічого не коштують і не записуються.
- Новий модуль маршруту (30-й)
server/lib/routes/usage.mjs—GET /api/usage(агрегати лише для читання) +server/lib/llm-usage.mjs(recordUsageнормалізує формати usage Anthropic/OpenAI/Gemini і додає best-effort;readUsage/aggregateагрегують за вікнами 24г/7д/30д/усе × провайдер) +server/lib/llm-pricing.mjs(редагована таблиця цін за провайдерами$/1Mтокенів — токени точні, долари — приблизні прайс-ціни, які можна виправити; не виставляються до оплати). Запис підключено в точках диспетчеризації (runActiveProvider+routes/llm.mjs). - Нове представлення
public/js/views/usage.js(#/usage, вкладки вікон). Тести:tests/usage-routes.test.mjs. 17 нових ключів i18n ×16 (usage.*+nav.usage). Довідка §6 розширена на місці.
Нове: server/lib/routes/usage.mjs; server/lib/llm-usage.mjs; server/lib/llm-pricing.mjs; public/js/views/usage.js.
[1.104.0] — 2026-07-06
Логотипи компаній у таблиці сканування (без витоку приватності). Новий перемикач Вигляд у Налаштуваннях — Показувати логотипи компаній у таблиці сканування (типово вимкнено) — малює логотип кожної компанії поруч із назвою на #/scan. Логотип — це favicon компанії, узятий з її власного домену та проксі на сервері (GET /api/logo), тож жоден сторонній сервіс логотипів не дізнається, яких роботодавців ви переглядаєте. Вакансії на спільному порталі (Greenhouse, Lever, Ashby, …) показують кольоровий літерний значок замість іконки порталу, і будь-який логотип, що не завантажився, відкочується на той самий значок.
- Новий модуль маршруту (29-й)
server/lib/routes/logos.mjs—GET /api/logo?domain=. Він валідує домен (без схеми/шляху/loopback), бере/favicon.icoчерез SSRF-безпечнийsafeGet(новий режимbinaryповертає сирі байти + content-type; DNS-піннінг, перевірка редиректів і ліміт розміру не змінені), виконує сніфінг сигнатури зображення, щоб ніколи не віддати HTML-сторінку помилки як картинку, кешує влучення і промахи в LRU у пам’яті та нічого не пише на диск. - Нова клієнтська бібліотека
public/js/lib/company-logo.js(window.CompanyLogo): типово вимкнена через прапорець у localStorage; пропускає спільні ATS-хости на користь детермінованого літерного аватара; CSP-безпечний відкатimg.onerror. Тести:tests/logo-routes.test.mjs. 5 нових ключів i18n ×16 (appear.*). Довідка §2 розширена на місці.
Нове: server/lib/routes/logos.mjs; public/js/lib/company-logo.js.
[1.103.0] — 2026-07-06
Налаштування: «Інструменти CLI для ШІ» — які встановлені. career-ops працює на Claude Code, але сумісний із будь-яким агентським CLI відкритого стандарту skills. Нова вкладка Інструменти CLI для ШІ у Налаштуваннях (#/config) показує, які з них — Claude Code, Codex, Gemini CLI, OpenCode, GitHub Copilot CLI, Qwen, Antigravity — встановлені на машині, де запущено сервер, і їхні шляхи. Це сканування PATH лише для читання: перевіряється лише наявність кожного бінарника, і він ніколи не запускається (без --version, без виконання), нічого не пишеться і дані користувача не зачіпаються.
- Новий модуль маршруту (28-й)
server/lib/routes/cli-detect.mjs—GET /api/cli-detect. Визначення резолвить шлях бінарника з фіксованого списку з 7 записів заprocess.env.PATH(шими.cmd/.exe/.batу Windows; біт виконання в POSIX); ворожий файл на PATH ніколи не буде виконано цим маршрутом. - Нова вкладка «Інструменти CLI для ШІ» у
public/js/views/config.js(лінива загрузка, діплінк через#/config?tab=cli). Тести:tests/cli-detect-routes.test.mjs. 8 нових ключів i18n ×16 (cli.*+config.tabCli). Довідка §2 розширена на місці.
Нове: server/lib/routes/cli-detect.mjs.
[1.102.0] — 2026-07-05
«Запитати довідку» — чат з опорою на вбудовану довідку. Нова сторінка Запитати довідку 💬 (бічна панель, під «Довідкою»): введіть запитання на кшталт «Як сканувати портали вакансій?» і отримайте відповідь лише зі вбудованої довідки застосунку вашою мовою — показує використані розділи й ніколи не читає ваше резюме, профіль чи пошук роботи. Це про те, як користуватися застосунком, а не про вас. З ключем LLM відповідає наживо; без ключа видає готовий промпт, уже заповнений потрібними розділами довідки.
- Новий модуль маршруту (27-й)
server/lib/routes/docs-assistant.mjs—POST /api/docs-assistant/ask. Пошук без залежностей: довідка вашою мовою розбивається на розділи##й оцінюється за збігом ключових слів із запитанням; найкращі включаються, і модель має відповідати з них або сказати, що довідка це не охоплює (без вигаданих функцій/маршрутів). Спільний каскад провайдерів, ручний відкат, обмеження частоти, без записів, не читає дані користувача. - Нове представлення
public/js/views/docs-assistant.js. Тести:tests/docs-assistant-routes.test.mjs. 14 нових ключів i18n ×16 (docs.*+nav.docsAssistant). Довідка §1 розширена на місці.
Нове: server/lib/routes/docs-assistant.mjs; public/js/views/docs-assistant.js.
[1.101.0] — 2026-07-05
CV Studio: адаптуйте резюме + напишіть супровідний лист під конкретну вакансію, з рекрутерським чек-лістом. Нова картка Адаптувати під вакансію на #/cv-studio: вставте опис вакансії (і, за бажанням, цільову роль/заголовок), і CV Studio створює адаптоване під цю вакансію резюме та відповідний супровідний лист, а потім проганяє обидва через чек-лист-гейт перед видачею — error блокує (виправляється до того, як ви побачите результат), warn радить. Механіка — витяжка з практики кар’єрного консультування в загальні правила: рекрутер читає за секунди, тож релевантне йде вгору, заголовок збігається з роллю вакансії, у результатах — конкретні цифри, а лист лишається коротким тизером з єдиною «смичкою» «вимога ↔ ваш відповідний факт». Ґрунтується лише на вашому резюме, профілі та two-pager і нічого не вигадує — без зашитих компаній, ролей чи історії.
- Новий ендпоінт
POST /api/cv-studio/tailor(розширює наявний модуль cv-studio — без 27-го модуля):buildTailorPrompt+ загальний гейтTAILOR_INSTRUCTIONS, на основіbundleProjectContext, спільний каскад провайдерів, ручний промпт без ключа, з обмеженням частоти, без записів. Результат експортується у Markdown / PDF / DOCX через спільну панельreport-export.js. - Тести: +3 у
tests/cv-studio-routes.test.mjs. 10 нових ключів i18n ×16 (cvs.tailor*). Загальний референсdocs/prompts/resume-cover.md. Довідка §24 розширена на місці.
Нове: docs/prompts/resume-cover.md.
[1.100.0] — 2026-07-05
Two-pager: ШІ-автозаповнення з вашого резюме + Перегляд + експорт у PDF/DOCX/Markdown. Two-pager (#/two-pager) фіксує те, чого ви насправді хочете від наступної ролі, але раніше кожне поле доводилося писати вручну або копіювати промпт в інший інструмент. Тепер ✨ ШІ-помічник заповнення працює наживо з налаштованим провайдером — читає лише ваше резюме + профіль (через bundleProjectContext, нічого не вигадуючи), складає всі поля (хто я / що подобається / обов’язкове / що ненавиджу / стоп-фактори / непорушне / цільове середовище) і заповнює форму, щоб ви перевірили, відредагували та зберегли. Без API-ключа повертається до модалки «скопіювати промпт», як раніше. Нова кнопка 👁 Перегляд і експорт відображає two-pager як форматований документ із панеллю Завантажити .md / Зберегти як PDF / Зберегти як DOCX / Копіювати.
- Експорт
.docxбез залежностей. Новийserver/lib/docx.mjsформує мінімальний, але валідний Office Open XML.docx(ZIP із DEFLATE із чотирьох частин OOXML, CRC-32 на запис) — без нової залежності (залежності лишаютьсяexpress+js-yaml). Новий маршрутPOST /api/export/docx(server/lib/routes/export.mjs, 26-й модуль маршрутів; без стану, ліміт 200 КБ, без записів / без LLM / без fetch за URL). Під’єднано до спільногоpublic/js/lib/report-export.js, тож звіт по ринку, кар’єрний план і профорієнтація теж отримують експорт у DOCX. - Живе автозаповнення використовує спільний каскад провайдерів (
runActiveProvider/providerAvailable); повернутий YAML парситься й приводиться назад до обмеженої форми two-pager (parseYamlFields+normalizeTwoPager) — невідомі ключі відкидаються, масиви/рядки обмежуються. Ручний режим збережено. - Тести:
tests/export-routes.test.mjs. 4 нові ключі i18n ×16 (export.saveDocx,twoPager.preview,twoPager.aiFilling,twoPager.aiFilled).
Нове: server/lib/docx.mjs; server/lib/routes/export.mjs.
[1.99.0] — 2026-07-05
Сторінка здоров’я порталів (#/portals). Сканер стежить за набором компаній у portals.yml; slug ATS може тихо зламатися, і цей роботодавець зникає з усіх майбутніх сканувань. Нова сторінка Portals перелічує кожну відстежувану компанію і за кнопкою Check portal health перевіряє кожен careers_url через safeGet із закріпленим DNS (захист від SSRF), позначаючи мертві (404 = тихо відкинута) — лише читання. Також посилює репортер багів v1.98.0 за підсумками ревʼю: кільцевий буфер помилок тепер ловить мережеві збої fetch, а скрабер вичищає непозначені ключі провайдерів.
Нове: server/lib/routes/portals.mjs; public/js/views/portals.js.
[1.98.0] — 2026-07-05
Вбудований репортер багів (паритет із веб-частиною web-v0.2.0 батьківського проєкту). Кнопка 🐞 Report a bug у панелі сповіщень збирає діагностичний знімок із пріоритетом приватності — версії, ваш екран, браузер, зведення перевірок /api/health і останні 20 помилок із нового клієнтського кільцевого буфера — плюс детермінований відбиток для дедуплікації (co-web-<base36>), дає переглянути точний Markdown і потім відкриває попередньо заповнений issue на GitHub. Нічого не надсилається автоматично; він ніколи не несе ваше CV, профіль, відповіді, URL вакансій чи ключі. Нові бібліотеки logbuf.js + bug-report.js; 11 ключів i18n ×16; tests/bug-report.test.mjs.
Нове: public/js/lib/logbuf.js; public/js/lib/bug-report.js.
[1.97.1] — 2026-07-05
Посилення за підсумками рев’ю та паритет документації (продовження v1.97.0). Розбір логів AI-рев’ю виявив реальні виправлення:
fit-score.js(значок відповідності◎під час сканування).salaryFloor()більше не перетворює ставку, меншу за річну, на фіктивний річний мінімум — «at least 500 EUR/day», «$80/hr», «6000 monthly» тепер повертаютьnullзамість дилбрейкера у 500k/80k. Зіставлення країн тепер іде за цілим словом (\b…\b), тож «Germany» більше не збігається з прикметником «German» (як і «Nigeria» всередині «Nigerian») і не спрацьовує хибним порушенням «обов’язково-деінде». +3 тести уtests/fit-score.test.mjs.- Паритет документації. Кожен локалізований README тепер однаково заявляє 16 локалей — лічильник/список у рядку Help (×13) та текст розділу локалізації плюс примітка «додайте ключ до всіх N файлів» (×8) усе ще трималися на лічильниках до v1.85 (8/9). Лічильник адаптерів §17 у вбудованій довідці виправлено на 46 адаптерів — 41 англійський + 5 російських в усіх 16 бандлах.
Жодних змін поведінки, окрім евристики значка відповідності; ні нових маршрутів, ні ключів, ні додавань i18n.
[1.97.0] — 2026-07-05
Джерело сканера Dassault Systèmes + фронт покращень якості за трьома напрямами.
- Нове джерело сканування — Dassault Systèmes (паритет із батьківським career-ops, #1498).
server/lib/sources/dassault.mjs+server/lib/portals/adapters/dassault.mjsвідтворюють zero-token-провайдер «карткового пошуку» Exalead із батьківського проєкту (публічна стрічка за3ds.com/careers/jobs). Це єдина глобальна кінцева точка, тож вона обирається за провайдером (provider: dassault) або автоматично визначається за хостом3ds.com, із захистом від SSRF, прив’язкою хоста доwww.3ds.comтаredirect:'error'. XML розбирається без DOM (карти<Meta>для кожного<Hit>), місто/країна беруться з локалізованого рядка категорії, а вакансії зберігаються лише тоді, коли їхній публічний URL перебуває на*.3ds.com. Реєстр тепер постачає 46 адаптерів (41 EN + 5 RU); лічильникALL_ADAPTERS, перевірки відсортованих id та EN-набору/api/scan/sourcesпідняті з 40 → 41. Набірtests/sources-dassault.test.mjs(10 випадків). - Перенесені з батьківського проєкту виправлення надійності. Парсер Avature тепер допускає два живі варіанти розмітки орендарів (
article--resultіз суфіксом позиційного індексу + безкласовий якір заголовка JobDetail, #1541); Get on Board захищається від0/від’ємногоpublished_at(більше жодних хибних дат 1970 року); SuccessFactors обмежує останню сторінку, щоб вона не могла перевищитиMAX_JOBS(#1528). - Виправлення серверного аудиту.
safe-fetchбільше не зависає на відповіді, що перевищує ліміт розміру — шлях обмеження розміру тепер напряму завершує проміс замість очікування події'end', яку зруйнований потік ніколи не випустить (виправляє запити/api/pipeline/previewта авто-пайплайну для великих сторінок). Логування активності SSEstream.*знову досяжне (перевірку/api/stream/переміщено вище загального захисту «пропускати GET»). - Виправлення аудиту SPA. Перемикач вкладок
#/statsзахищений від гонки під час асинхронного рендерингу — результат повільної вкладки більше не може затерти новішу вкладку, на яку користувач уже перемкнувся. Підтвердження видалення у mock interview та нетворкінгу тепер передають коректні заголовок + тіло (більше жодних діалогів із порожнім тілом). - Виправлення перекладу. Виправлено неперекладені значення словника — українські
config.modes*(Adaptive Framing / Exit Narrative / Location Policy), російськийeval.jdLbl(«Job Description»), італійськийdash.quick.contactoSub(«referral» → «segnalazione») — а також англійську заготовку 16 локалей локалізовано в CHANGELOG для ru/uk/ja/ko/zh-CN/zh-TW.
Нове: server/lib/sources/dassault.mjs; server/lib/portals/adapters/dassault.mjs.
[1.96.0] — 2026-07-04
Кар’єрна орієнтація (Epic 27). Нова сторінка #/orientation відповідає на питання «які напрями мені насправді підходять?» — така оцінка, яку дав би профорієнтаційний тест, але виведена з вашого власного резюме та профілю замість опитувальника. Натисніть Згенерувати профіль, і модель поверне ваші найкращі кар’єрні вектори (які з восьми архетипів — Функціоналіст, Адміністратор, Комунікатор, Спеціаліст, Аналітик, Новатор, Менеджер, Підприємець — підходять, з доказами), схильність до кар’єрного типу, рекомендовані ролі, професійні сильні сторони, прив’язані до вашого резюме, тенденції робочого стилю та рекомендації щодо розвитку. Це ШІ-рефлексія того, як читається ваше резюме, — а не психометричний тест: воно ніколи не вигадує досягнень і ніколи не подає числових результатів так, ніби їх виміряли. Експортуйте його в Markdown або PDF; нічого не записується на диск.
- Новий маршрут
server/lib/routes/orientation.mjs(24-й модуль маршрутів) —POST /api/orientation/generateбудує промпт профілю з CV+профілю+two-pager+пам’яті через спільну каскаду провайдерів, із ручним відкатом для копіювання-вставлення та без запису файлів. - Повторно використовує
report-export.jsдля Markdown/PDF/копіювання, у навігаційній групі Зростання. - Тести:
tests/orientation-routes.test.mjs(рамка рефлексії / без вигаданих оцінок, ручний режим із засівом із CV/профілю). 7 нових ключів i18n ×16 локалей, довідка §28 ×16.
Нове: #/orientation; server/lib/routes/orientation.mjs.
[1.95.0] — 2026-07-04
План кар’єри (Epic 26). Нова сторінка #/career-plan перетворює ваше резюме та профіль на конкретний, персоналізований план розвитку. Виберіть горизонт (6/12/24 місяці) та, за бажанням, фокус, і модель — читаючи ваше CV, профіль, two-pager і нотатку пам’яті — пише знімок відправної точки, SWOT сильних сторін і зростання, цілі у форматі SMART / OKR / WOOP, альтернативні траєкторії, план hard/soft-навичок, помісячну дорожню карту, методи відстеження прогресу, підводні камені та підтримувальні кроки. Вона планує вперед від того, що дійсно показують ваші матеріали, і ніколи не вигадує факти про вашу історію. Редагуйте її на місці, Збережіть її в користувацький шар (config/career-plan.md) та експортуйте її у Markdown або PDF.
- Новий маршрут
server/lib/routes/career-plan.mjs(23-й модуль маршрутів) —GET/PUT /api/career-plan(пишеconfig/career-plan.md) +POST /api/career-plan/generate(спільна каскада провайдерів, ручний відкат, без фабрикації).PATHS.careerPlan. - Повторно використовує спільний
report-export.js(v1.94.0) для Markdown/PDF/копіювання та нову навігаційну групу Зростання. - Тести:
tests/career-plan-routes.test.mjs(обмеження, круговий обхід GET/PUT, промпт із урахуванням горизонту, засіяний із CV/профілю). 20 нових ключів i18n в усіх 16 локалей, довідка §27 ×16.
Нове: #/career-plan; server/lib/routes/career-plan.mjs; PATHS.careerPlan.
[1.94.0] — 2026-07-04
Статистика, перероблена (Epic 25). Сторінка #/stats тепер є розділом Статистика з трьома вкладками, зі справжніми графіками та значно більшою кількістю даних. Нова вкладка Звіт про ринок просить модель проаналізувати зарплати та ринок праці для ваших цільових ролей у вибраному регіоні та валюті — стисле резюме, зарплати за рівнем із перцентилями P10/P25/P75/P90, провідні роботодавці, таблиця затребуваних навичок, частота пільг, розподіл офіс/гібрид/віддалено, тренди на 12–24 місяці та поради щодо перемовин. Кожна цифра позначена як орієнтовна оцінка зі знань моделі, і ніколи не подається як зібрані дані. Нова вкладка Мій пайплайн будує графіки за вашим власним трекером: розподіл оцінок, воронка статусів, провідні компанії та ролі, заявки в часі та коефіцієнти конверсії. Початковий вигляд цільових ролей (вакансії/зарплати за країнами + тренд збережених знімків) переходить у третю вкладку, тепер із вибором валюти та оглядом вакансій за роллю.
- Експортуйте будь-який звіт у Markdown або PDF чи скопіюйте його — через спільний помічник
report-export.js(завантаження Markdown як blob; PDF через наявний вбудований PDF-раннер). - Новий маршрут
server/lib/routes/market.mjs(22-й модуль маршрутів) —POST /api/stats/marketбудує промпт аналізу ринку на основі вашого CV/профілю (щоб знати ваші цільові ролі), регіону та валюти, запускає його через спільну каскаду провайдерів і відкочується до промпту для копіювання за відсутності ключа. Без запису файлів. - Тести:
tests/market-routes.test.mjs(обмеження регіону/валюти, промпт із чесним маркуванням, ручний режим із передзаповненням із CV/профілю). 36 нових ключів i18n в усіх 16 локалей, довідка §26 ×16.
Нове: #/stats перероблено на вкладки; server/lib/routes/market.mjs; public/js/lib/report-export.js.
[1.93.0] — 2026-07-04
Шар пам’яті (Epic 24). Нова сторінка #/memory містить коротку редаговану нотатку «запам’ятай це про мене», яку асистент тримає в голові на кожному завданні:
- Одна нотатка, всюди — оскільки вона вбудована в
bundleProjectContext, нотатка автоматично доходить до кожного AI-запиту (оцінка, пробна співбесіда, нетворкінг, CV Studio) в усіх провайдерах. Напишіть її раз — вона керує всім. - Керування, а не факти — вона фіксує ваші вподобання й те, як вам зручно працювати (тон, формат, стоп-фактори, ритм), і ніколи не нові фактичні твердження про ваш досвід — ті й далі живуть лише у вашому резюме, профілі та two-pager. Зберігається в користувацький шар за адресою
config/memory.mdі ніколи не перезаписується оновленнями. - Підказки з ваших даних —
POST /api/memory/suggestаналізує ваш власний трекер заявок на поведінкові патерни й готує пункти для перегляду й редагування. Він читає ваш трекер; ніколи не вигадує фактів і не робить жодного онлайн-виклику.
Нове: server/lib/routes/memory.mjs (21-й модуль маршрутів — GET/PUT /api/memory + POST /api/memory/suggest), public/js/views/memory.js, PATHS.memory та блок config/memory.md, доданий до bundleProjectContext. 11 нових ключів i18n в усіх 16 локалей. Тести: tests/memory-routes.test.mjs.
[1.92.0] — 2026-07-04
CV Studio (Epic 21). Нова сторінка #/cv-studio дає вашому резюме три чесні, здебільшого локальні інструменти:
- Діагностика резюме — детермінована оцінка 0–100 із поясненнями за кожною перевіркою (кількісно виміряний вплив, слабкі дієслова, штампи, обсяг, ключові розділи, контактні дані). Повністю на боці клієнта (
window.CvDiagnostics) — без LLM, нічого вигаданого, кожен висновок пояснено, тож ви вирішуєте, що змінювати. - Маска приватності — вилучення PII (email, телефон, посилання/нікнейми, поштова адреса й за бажанням ваше ім’я → ініціали) перед тим, як поділитися резюме як зразком чи скриншотом. Виконується цілком у браузері (
window.CvPrivacy); повідомляє, що саме було вилучено, і ніколи не зберігає оригінал. - Make it human / збіг голосу — вставте суху фразу чи абзац і перепишіть її вашим голосом, обґрунтованим на боці сервера через
voice-dna.mdіwriting-samples/. Жорсткий запобіжник: воно може переставляти, стискати й переголошувати, але ніколи не додає факту, метрики чи досягнення, якого ще немає в тексті. Виконується наживо через спільний каскад провайдерів або повертає готовий до копіювання промпт без ключа.
Нове: server/lib/routes/cv-studio.mjs (20-й модуль маршрутів — POST /api/cv-studio/humanize), public/js/views/cv-studio.js, public/js/lib/cv-diagnostics.js, public/js/lib/cv-privacy.js, PATHS.voiceDna + PATHS.writingSamplesDir. 29 нових ключів i18n в усіх 16 локалей. Тести: tests/cv-diagnostics.test.mjs, tests/cv-studio-routes.test.mjs. (Галерея шаблонів, експорт у Word та архів PDF-оголошень відстежуються як подальша робота над CV Studio.)
[1.91.0] — 2026-07-04
Нетворкінг і глибоке дослідження компаній (Epic 16). Нова сторінка #/networking перетворює компанію на дієвий план отримання співбесіди, обґрунтований вашим резюме, профілем і two-pager:
- Досьє компанії — стислий бриф про те, чим займається компанія, нещодавні сигнали, варті згадування, і зачіпки «чому я підходжу», взяті з вашого реального досвіду.
- З ким зв’язатися — 3–5 цільових персон (наймальний менеджер, внутрішній рекрутер, старший IC з команди, теплий контакт/випускник того самого вишу) з конкретним пошуковим рядком LinkedIn для пошуку кожного. Реальні імена ніколи не вигадуються.
- Найтепліший шлях для представлення — найреалістичніший теплий вхід саме для вашого досвіду (спільний роботодавець/навчальний заклад/спільнота, шлях другого рівня або сильний за сигналом холодний DM) і чому.
- Чернетки для контакту — короткі, конкретні повідомлення для головних персон, обґрунтовані вашими реальними точками доказу.
- Наживо або вручну — виконується наживо через спільний каскад провайдерів із будь-яким ключем або повертає готовий до копіювання промпт (чесний fallback, нічого вигаданого). Зберегти план зберігає готовий план у користувацький шар (
networking/net-{company}-{role}-{date}.md); сторінка показує список, відкриває й видаляє збережені плани.
Нове: server/lib/routes/networking.mjs (19-й модуль маршрутів), public/js/views/networking.js, PATHS.networkingDir. Повторно використовує каскад server/lib/llm-dispatch.mjs з v1.90.0. 24 нові ключі i18n в усіх 16 локалей. Тести: tests/networking-routes.test.mjs.
[1.90.0] — 2026-07-04
Mock Interview 2.0 (Epic 15). Нова сторінка #/mock-interview перетворює ваше резюме, профіль, two-pager і банк історій на покрокову репетицію співбесіди:
- Діалогова практика — задайте цільову роль (+ за бажанням компанію / JD), і інтерв’юер починає з точкового запитання. На кожну надіслану відповідь ви отримуєте структуровану репліку: Feedback (сильні сторони + прогалина за STAR+R), Score (
N/5) та Next question, яке промацує найслабше місце вашої останньої відповіді. Обґрунтовано на боці сервера вашими реальними матеріалами — воно ніколи не вигадує досвід, якого у вас немає. - Враховує банк історій —
interview-prep/story-bank.mdвбудовується в промпт (той самий рівень довіри, що йcv.md), тож зворотний зв’язок може вказати вам на ваші ж найкращі історії. - Наживо або вручну — за наявності ключа провайдера хід виконується наживо через спільний каскад провайдерів (Anthropic → Gemini → OpenAI → Qwen → OpenRouter → GitHub Models); без ключа ви отримуєте готовий до запуску промпт для копіювання та вставлення (чесний fallback, без вигаданих відповідей).
- Збережені сесії — натисніть Save transcript, щоб зберегти завершену співбесіду в шар користувача (
interview-prep/mock-{company}-{role}-{date}.md); сторінка показує список, відкриває та видаляє збережені сесії.
Нове: server/lib/routes/interview.mjs (18-й модуль маршрутів), public/js/views/mock-interview.js, server/lib/llm-dispatch.mjs (спільний каскад провайдерів), PATHS.storyBank, bundleProjectContext({ extraFiles }). 30 нових ключів i18n в усіх 16 локалей. Тести: tests/interview-routes.test.mjs.
[1.89.0] — 2026-07-04
Відповідність кандидата й ринку — two-pager (Epic 14). Нова сторінка #/two-pager дозволяє зафіксувати те, чого ви насправді хочете від наступної ролі, за зразком «Mnookin two-pager» із книги Never Search Alone:
- Покроковий конструктор — оповідь від першої особи «Хто я», нотатка «Цільове середовище» та п’ять редакторів списків-чипів: loves, must-haves, hates, deal-breakers і non-negotiables. Зберігається в користувацький шар батьківського проєкту (
config/two-pager.yml) черезPUT /api/two-pager— ніколи не перезаписується системними оновленнями. - ШІ-помічник заповнення (
POST /api/two-pager/draft) — збирає готовий до запуску Mnookin-промпт із вбудованими вашими CV + профілем, щоб ви запустили його в будь-якому LLM і вставили результат назад. Він використовує лише ваші власні матеріали; нічого не вигадується. - Бейдж відповідності-тому-що-ви-хочете — кожна вакансія на
#/scanтепер показує оцінку відповідності◎ N(на боці клієнта, черезwindow.FitScore), що зіставляє формат роботи, країну, мінімальну зарплату та релокацію вакансії з вашим two-pager. Чесний за задумом: якщо вакансія не дає зіставного сигналу, бейдж не показується (ніколи не вигадане число). Порушення deal-breakers важать більше, ніж легкі неприязні. - Живить кожну оцінку — збережений two-pager вбудовується в
bundleProjectContext, тож усі подальші оцінки LLM поєднують заявлені вами вподобання з відповідністю CV-проти-JD.
Нове: server/lib/routes/two-pager.mjs, public/js/views/two-pager.js, public/js/lib/fit-score.js, PATHS.twoPager. 27 нових ключів i18n в усіх 16 локалях. Тести: tests/two-pager-routes.test.mjs, tests/fit-score.test.mjs.
[1.88.0] — 2026-07-04
Доопрацювання issue #29 — прогалини i18n у Скануванні + гігієна API.
- Локалізовано останні захардкоджені рядки Сканування (дорожня карта v1.69.4): плашки зведення за джерелом (
N нових / M збігів), тостиN нових вакансійта бейджrelocтепер проходять черезt()— 4 нові ключі (scan.pillNew,scan.pillMatching,scan.newOffers,scan.relocBadge) в усіх 16 локалях. Неангломовні користувачі більше не бачать випадкової англійської в основному потоці сканування. - Вимкнено заголовок
X-Powered-By(дорожня карта v1.69.5):app.disable('x-powered-by')уcreateApp()— сервер більше не повідомляє, що працює на Express. (Решту цього епіку вже було випущено:parentVersionвирізає свій коментар release-please, перемикач світлої теми, закриття модальних вікон під час зміни маршруту та локалізація «Score» (rep.score) у Звітах.)
Тести: tests/scan-i18n-gaps.test.mjs + перевірка відсутності X-Powered-By у tests/security-headers.test.mjs.
[1.87.0] — 2026-07-04
4 нові провайдери сканування без автентифікації (паритет із батьківським career-ops v1.16.0). Реєстр сканера зростає з 41 → 45 адаптерів (40 EN + 5 RU) — усі публічні, без автентифікації, із закріпленим хостом, redirect:'error' (захист від SSRF), кожен з ізольованим для CI тестом:
- Get on Board (
getonbrd) — публічний JSON:API по всьому порталу (LATAM/віддалені технічні ролі), обирається за провайдером, із пагінацією.server/lib/sources/getonbrd.mjs. - Amazon (
amazon) — публічний JSON пошукуamazon.jobs, визначається за хостом абоprovider: amazon, пагінація за зміщенням.server/lib/sources/amazon.mjs. - Avature (
avature) — ATS*.avature.netдля кожного орендаря, парсинг HTML, визначається за хостом абоprovider: avature.server/lib/sources/avature.mjs. - SAP SuccessFactors (
successfactors) — список плиток RMK для кожного орендаря (*.successfactors.eu/.com,jobs2web.com), парсинг HTML.server/lib/sources/successfactors.mjs.
Кожен постачає sources/<slug>.mjs (автовиявлюваний meta → випадний список #/scan) та portals/adapters/<slug>.mjs у ALL_ADAPTERS (правило двох реєстрів) + tests/sources-<slug>.test.mjs. Лічильник ALL_ADAPTERS, а також перевірки відсортованих id та EN-набору /api/scan/sources зросли з 36→40; GET /api/scan/sources тепер перелічує 45.
[1.86.0] — 2026-07-03
Статистика за цільовими ролями (#/stats) — ринкова статистика вакансій і зарплат за ВАШИМИ цільовими ролями. Нова сторінка Аналітики читає ваші цільові ролі з профілю (config/profile.yml → не захардкоджені) та вакансії з останнього сканування, а потім показує для кожної ролі й країни:
- Вакансії за країнами та медіанну зарплату за країнами (USD) — агрегуються на боці клієнта (
public/js/lib/role-stats.js, повторно використовуючиwindow.Countries) з розріджених даних, які сканери вже збирають. Зарплати в будь-якій валюті нормалізуються до USD через явно приблизну таблицю FX, із застереженням щодо розміру вибірки — ніколи не вигадуються. - Фільтри ролі та країни й саморобні вбудовані SVG-графіки: стовпчикові та трендові (без нових залежностей, безпечно для CSP — лише
addEventListener). - Зберегти знімок (
POST /api/stats/snapshot) зберігає поточний агрегат уdata/role-stats.jsonl; графік тренду (GET /api/stats/trend) відстежує кількість вакансій у часі — подання «динаміки». Чесний гібрид: знімки формуються з локальних даних сканування й оновлюються за запитом. - Повністю локалізовано в усіх 16 локалях (26 нових ключів i18n).
Нове: server/lib/routes/stats.mjs (16-й модуль маршрутів), public/js/lib/role-stats.js, public/js/views/stats.js, PATHS.roleStats; тести role-stats.test.mjs (7) + stats-routes.test.mjs (5).
[1.85.0] — 2026-07-03
Локалі німецької, італійської та турецької (паритет локалей із батьківським career-ops v1.16.0). Інтерфейс тепер постачається 16 мовами — de 🇩🇪, it 🇮🇹 і tr 🇹🇷 додаються до наявних 13.
- Повний переклад інтерфейсу — усі 730 ключів i18n перекладено в
public/js/lib/locales/i18n-dict.{de,it,tr}.js; перемикач мов показує Deutsch / Italiano / Türkçe, а автовизначення мови браузера розпізнаєde/it/tr(public/js/lib/i18n.js). - Вбудований довідковий посібник —
docs/help/{de,it,tr}.mdперекладено (повна структура з 19 H2 / 75 H3), надаються черезGET /api/help/:lang. - Документація — додано
README.{de,it,tr}.mdіCHANGELOG.{de,it,tr}.md; перевірка паритету локалей CHANGELOG тепер охоплює 15 не-EN локалей. - Каркас промптів —
server/lib/prompts.mjs(LOCALE_NAMES+SCAFFOLD_STRINGS) локалізовано для трьох нових локалей, тож вивід LLM дотримується мови інтерфейсу.
Усі перевірки паритету (i18n-locale-files, i18n-coverage, check-changelog-parity, lang-switcher-rtl) розширено на набір із 16 локалей.
[1.84.0] — 2026-06-30
Кулдаун повторних заявок + компенсація в pipeline.md (паритет із батьківським career-ops v1.15.0). Два покращення сканера:
- Кулдаун повторних заявок (#1201): EN-скан тепер пропускає ролі в компаніях, до яких ви нещодавно вже подавали заявку, — результати лишаються зосередженими на НОВИХ вакансіях. Налаштуйте часові вікна на рівні компанії в
config/profile.ymlу секціїre_apply_windows:(last_apply_date,same_role_days,applied_to: [roles], необов’язковийcross_role_bucket); порівняння компаній нечутливе до пунктуації й працює за межами слів (server/lib/cooldown.mjs). Не діє, якщо ключ відсутній; до журналу сканування виводитьсяCooldown skipped: N. - Компенсація в pipeline.md (#1017): знайдені під час сканування вакансії тепер зберігають зарплату у вигляді необов’язкового кінцевого стовпця (
url | <salary>) уdata/pipeline.md. URL залишається ключем дедуплікації (стовпець| compприбирається під час читання), значення комірки санується (без ін’єкції рядка/стовпця, формульний префікс нейтралізується), а pipeline у форматі «лише URL» зберігає зворотну сумісність.
Постачається з tests/cooldown.test.mjs і тестами компенсації для pipeline. Кількість джерел не змінилась — 41 (обидва покращення стосуються логіки сканування, а не нових дошок).
[1.83.0] — 2026-06-30
Детектор повторних публікацій / фантомних вакансій (паритет із батьківським career-ops v1.15.0). На сторінці #/scan з’явилася панель 🔁 Повторні публікації / фантомні вакансії, яка позначає кластери «компанія + посада», повторно розміщені під різними URL у ковзному 90-денному вікні — сигнал застарілих конвеєрів і фантомних оголошень. Базується на нечіткому порівнянні заголовків (server/lib/role-matcher.mjs) та read-only детекторі (server/lib/detect-reposts.mjs) по data/scan-history.tsv, надається через GET /api/scan/reposts. Також: parentVersion у /api/health тепер повертає лише semver (коментар # x-release-please-version від release-please прибирається). Постачається з tests/detect-reposts.test.mjs. Кількість джерел не змінилась — 41: повторні публікації — аналітична функція, а не нова дошка.
[1.82.0] — 2026-06-30
Джерело сканування NoDesk (паритет із батьківським career-ops v1.15.0). Загальнодошкова RSS-стрічка віддаленої роботи NoDesk тепер повноцінне джерело — додайте запис provider: nodesk, і воно з’явиться у списку Source на #/scan (загалом 41 адаптер: 36 EN + 5 RU). Хост закріплено за nodesk.co із redirect:'error' (захист від SSRF); заголовки діляться за Role at Company (NoDesk не має тегу локації, поле місцеположення залишається порожнім); усі вакансії — віддалені. Постачається з CI-ізольованим набором тестів tests/sources-nodesk.test.mjs; повний набір юніт-тестів зелений, 1523.
[1.81.0] — 2026-06-29
Паритет із батьківським career-ops — 13 нових джерел сканування вакансій. Переносить останній пакет провайдерів із main Fighter90/career-ops у вбудований сканер. Загальнодоступні API дошок (вибір за provider:): Arbeitnow, Himalayas, Jobicy, Landing.jobs, 4 Day Week, The Muse, The Hub, Jobspresso (RSS) і Hacker News “Who is hiring?” (Algolia, два кроки). Польські дошки (визначаються за хостом або provider:): JustJoin.it і NoFluffJobs (POST-пошук). Per-tenant ATS (автовизначення за careers_url): Pinpoint (<slug>.pinpointhq.com/postings.json) і Rippling (ats.rippling.com/<slug> → api.rippling.com board). Кожне джерело закріплено за хостом із redirect:'error' (захист від SSRF) і доступне у списку Source на #/scan — реєстр тепер налічує 40 адаптерів сканера (35 EN + 5 RU). Додано 13 CI-ізольованих наборів тестів на джерело; повний набір юніт-тестів зелений, 1513.
[1.80.0] — 2026-06-28
П’ять покращень сканера (ідеї з job-crawler, переписані). (1) Джерело Teamtailor — сайти <slug>.teamtailor.com через публічну стрічку /jobs.rss, автовизначення за careers_url (хост закріплено + redirect:'error'); у реєстрі тепер 27 адаптерів. (2) Карантин джерел — джерело зі сталим 404/410 записується в data/scan-quarantine.json і пропускається в наступних сканах (самовідновлення: повтор через 14 днів). (3) Макс. на джерело — необов’язкове поле на #/scan, що обмежує кількість вакансій з борду (∞ за замовчуванням). (4) Опубліковано за — клієнтський фільтр за віком (24г / 7д / 30д). (5) Збережені пошуки + ★ обране — називайте й повторно використовуйте набори фільтрів і позначайте вакансії, у localStorage із захисною валідацією (пошкоджений кеш скидається чисто); кеш результатів скидається перед скануванням і наповнюється наживо.
[1.79.0] — 2026-06-28
Джерело сканування WeWorkRemotely (паритет із career-ops v1.14.0). Загальнодошкова RSS-стрічка віддаленої роботи We Work Remotely тепер повноцінне джерело — додайте запис provider: weworkremotely, і воно з’явиться у списку Source на #/scan (26 адаптерів загалом). Хост закріплено за weworkremotely.com із redirect:'error' (захист від SSRF); заголовки діляться за Company: Role. Також: ключові слова title_filter тепер обрізаються перед перевіркою довжини (parent #1261).
[1.78.2] — 2026-06-27
Зміцнення i18n та UX (виправлення після v1.78.1). Доступна назва логотипа тепер локалізована всіма 13 мовами (nav.logoHome). Enter у глобальному пошуку, коли ви вже на #/scan, примусово ре-рендерить, щоб не втратити введений термін (guard тієї ж маршрутизації). health.title тепер перекладено польською (Kondycja) та данською (Systemtilstand) — раніше англійською. Тести 1235 → 1238.
[1.78.1] — 2026-06-27
Виправлення UX на Scan. Таблиця результатів #/scan тепер автоматично оновлюється під час сканування та ще раз після завершення — без перезавантаження. Глобальний пошук у шапці показує підказку Enter і за не-URL-запитом переходить на #/scan із заповненим полем (раніше #/tracker). Логотип тепер веде на дашборд (головну).
[1.78.0] — 2026-06-27
Гео-фільтр на сторінці Scan — фільтр вакансій за країною, з прапорцями. Новий список Країна у #/scan показує кожну країну, виявлену в результатах (емодзі-прапор + лічильник), щоб лишити лише ролі, прив’язані до країни — поряд із фільтром Remote/Hybrid/Onsite, тож можна шукати як прив’язану до країни, так і віддалену роботу. На основі нового помічника countries.js, що зіставляє вільний текст локації (назви країн, аліаси та ~100 великих міст) з країною ISO + прапором; детекція консервативна й ніколи не вгадує.
[1.77.0] — 2026-06-27
Додано данську (Dansk) — 13-ту мову інтерфейсу. Повний переклад UI, вбудованого довідника Help (19 H2 / 75 H3), README та CHANGELOG. Данська додана до перемикача мов із прапорцями; механіка i18n (асемблер, аудит, перевірки паритету, знімок) тепер охоплює 13 локалей.
[1.76.0] — 2026-06-26
Паритет із career-ops v1.13.0 — шість нових джерел, зміцнення сканера та таблиця результатів без ліміту.
Додано
- Шість ATS-джерел на тенант — BambooHR, Breezy HR, Comeet, Personio, Recruitee, SolidJobs. Визначаються за хостом
careers_url(Comeet потребує повногоapi:); кожен хост закріплено якірним regex +redirect:'error'(захист від SSRF). Доступні у списку Source на#/scan— реєстр тепер має 25 адаптерів (20 EN + 5 RU). Додано помічникfetchTextдля XML-стрічки Personio. trust_filter— необов’язкова оцінка довіри (0–100, рівень high/medium/low, прапорці), лише анотує. Рядки нижчеhighотримують нейтральний значок ⚠ на#/scan; нічого не відкидається.- Arbeitsagentur
remoteMatch+remoteMaxPages— визначення віддаленої роботи з конфігу:title,filter(homeoffice=nv_trueна сервері + пагінація) абоoff.
Змінено
- Немає ліміту результатів.
MAX_STORED_RESULTS(2000) прибрано — зберігаються всі збіги, таблиця#/scanгортає їх (200/стор.). - Надійність фільтра заголовків — короткі абревіатури (COO, SDR…) збігаються за межами слів; некоректний
title_filterбільше не ламає скан. Обидва сканери.
Тести
- +32 кейси (1190 → 1222):
sources-ats-providers,title-filter,arbeitsagentur-remote,trust-validatorі переписаний стражscan-result-cap(«без ліміту»).
[1.75.2] — 2026-06-19
docs: повний паритет документації для агрегаторів сканера з v1.75.0 в усіх 12 локалях. Без зміни коду — приводить документацію для користувача у відповідність до семи джерел, що з’явилися в v1.75.0:
- Довідковий посібник (12 локалей). §5 отримує блок
content_filter(гейтинг за ключовими словами опису/сніпета, аналогlocation_filter) та примітку про агрегатори; §7 перелічує сім нових джерел у проході сканування в один клік та в повному переліку випадного списку Source; лічильник адаптерів у §17 виправлено зі застарілого «11 adapters» на «19 adapters — 14 English + 5 Russian». Заголовків##/###не додавалося, тож закріплена структура 19 H2 / 75 H3 залишається незмінною. - README (9 повних локалей). Новий пункт «Aggregator boards (v1.75.0)» під джерелами сканування, плюс значок релізу, оновлений до v1.75.2. (Скорочені README pl/uk/ar не мають списку за джерелами, і там вони навмисно не зачеплені.)
- Довідкові документи.
docs/portals-examples.mdотримує готовий до копіювання розділ «Aggregator boards» з точними блоками конфігураціїprovider:/<provider>:для всіх семи;docs/PROJECT.mdоновлено до 19 adapters;docs/sdd/CONVENTIONS.mdдокументує розрізнення двох реєстрів (sources/registry.mjsдля випадного списку протиportals/registry.mjsдля вибірки), вибір агрегатора на основіprovider:, що передається якopts.company, санітайзер запису сканування (scan-sanitize.mjs) та кількість тестів v1.75.1 (1190). - QA. Додано
qa/QA-REGRESSION-PROMPT-v1.75.2-FULL.md— драйвер релізного шлюзу за повною поверхнею, оновлений під цикл агрегаторів сканування v1.75.x.
[1.75.1] — 2026-06-19
fix(scan): доопрацювання надійності джерел на основі конфігурації з v1.75.0. Три невеликі зміцнювальні виправлення за підсумками післярелізного розбору (без зміни поведінки за штатного сканування):
- Паузи пагінації з урахуванням скасування. Міжсторінкові ввічливі паузи Glints (300 мс) та Jobstreet/SEEK (200 мс) тепер негайно завершуються, коли спрацьовує
AbortSignalсканування — через новий помічникdelay(ms, signal)уserver/lib/http-json.mjs, тож від’єднаний клієнт не може утримувати пагіноване сканування відкритим ще на одну паузу. - Описова помилка для не-JSON відповіді.
fetchJsonтепер загортає не-JSON тіло з кодом2xx(наприклад, HTML-сторінку обслуговування, віддану зі статусом 200) якnon-JSON 2xx response from <url>, замість того щоб видавати голийSyntaxError, тож журнал помилок сканера за кожним джерелом називає некоректно поводжуваний ендпоінт. - Посилена нормалізація запису сканування.
normalizeScanScalarтепер згортає вертикальну табуляцію, переведення сторінки та розділювачі рядка/абзацу Unicode (\v \f U+2028 U+2029) на додачу до\r \n \t— суворий надмножина, тож жоден розділювач запису/рядка, який могли б врахувати таблиця чи переглядач, не потрапляє доscan-history.tsv.
[1.75.0] — 2026-06-19
feat(scan): переносить паритет з батьківським career-ops v1.12.0 — сім нових джерел вакансій, фільтрація контенту та виправлення безпеки/якості. web-ui запускає власні внутрішньопроцесні сканери (він не викликає shell out до батьківського scan.mjs), тож зміни провайдерів і сканування з батьківської v1.12.0 не надходять автоматично — цей реліз переносить застосовні з них згідно з контрактом адаптерів web-ui.
- Сім нових джерел сканера. Три глобальні агрегатори віддалених вакансій — RemoteOK, Remotive, Working Nomads — вписуються в автоматично виявлюваний патерн
server/lib/sources/*.mjs(обираються черезprovider: remoteok/remotive/workingnomads). Чотири керовані конфігурацією регіональні агрегатори — careers IBM, Arbeitsagentur (німецьке Федеральне агентство зайнятості), Glints (Південно-Східна Азія), Jobstreet / SEEK — читають поелементний конфігураційний блок<provider>:; en-scanner тепер прокидає розв’язаний запис компанії аж до кожного фетчера, щоб вони могли його прочитати. Усі сім автоматично з’являються у випадному списку джерел#/scan. content_filter(батьківський #974). Необов’язковий блокportals.yml(списки ключових слівpositive/negative), що фільтрує вакансію за текстом її опису/сніпета — повторює семантикуlocation_filter; вакансії без опису завжди проходять. Підключений до обох сканерів — EN і RU.- Посилення запису під час сканування (батьківський #1098). Метадані зовнішніх стрічок тепер санітизуються перед потраплянням у
data/scan-history.tsvтаdata/pipeline.md: керівні символи згортаються (перенесення рядка в назві компанії/посади більше не може ін’єктувати рядок TSV), а провідні= + - @нейтралізуються проти ін’єкції формул електронних таблиць. secondaryLocationsAshby (батьківський #1073). Джерело Ashby тепер згортає мітку регіону кожної вторинної локації разом із поштовимиaddressLocality/addressCountryу рядок локації (з дедуплікацією), тож роль із правом працювати в ЄС, чия основна мітка читається, наприклад, як “Canada”, спливає дляlocation_filter.- Валідація форми звіту про оцінку (батьківський #819). Внутрішньопроцесні провайдери
/api/evaluate(Anthropic / OpenAI / Qwen / OpenRouter / GitHub Models) тепер позначають некоректний звіт A–G /SCORE_SUMMARYяк нефатальний масивwarnings; шлях оцінки Gemini вже успадковує цей захист від батьківськогоgemini-eval.mjs. - docs: Antigravity CLI додано до списків підтримуваних асистентів у всіх 12 README (зіставляється з провайдером Gemini).
Успадковано безкоштовно з git pull батьківського проєкту (web-ui викликає їх через shell out): резервні шрифти CJK для японського PDF (#1053), ATS-сумісні шрифти PDF (#1074), захист CJK для LaTeX (#1054), виправлення tracker/merge/followup/dashboard і китайські режими modes/zh (web-ui перелічує режими динамічно).
[1.74.3] — 2026-06-18
docs(parent-source): спрямовує батьківський репозиторій career-ops на форк Fighter90/career-ops. web-ui тепер посилається на форк супровідника як на батьківський проєкт усюди, де це реальне джерело: типове значення CAREER_OPS_REPO в інсталяторі bin/setup.sh, кожне посилання git clone / «побудовано на основі» / онбординг у всіх 12 README, а також документація агентів (CLAUDE.md, AGENTS.md, GEMINI.md, .github/copilot-instructions.md, docs/). Зазначення авторства santifer (та застереження про неофіційний інтерфейс) не змінилося — перемістилися лише URL джерела/клонування. tests/sh-files.test.mjs тепер перевіряє, що інсталятор клонує форк.
[1.74.2] — 2026-06-17
fix(health): відображення GITHUB_MODELS_API_KEY як необов’язкової перевірки на #/health та в /api/status/providers. Провайдер GitHub Models із v1.74.0 налаштовувався в #/config, але не мав рядка на сторінці Health і був відсутній у провайдерській поверхні keysConfigured. Додано необов’язкову перевірку (з тим самим формулюванням “set / unset (manual mode)”, що й у решти п’яти провайдерів живого оцінювання) та github (+ його GITHUB_MODELS_MODEL) до /api/status/providers, тож маршрутизація активного провайдера й сторінка Health тепер відображають усі шість. Тест рядка health у tests/api.test.mjs розширено на всі шість провайдерів.
[1.74.1] — 2026-06-17
docs + test: розділ README «Встановлення ШІ-асистента»; повне покриття гілок для конектора Gemini. До README додано таблицю встановлення/входу — посилання для встановлення Claude Code / Gemini CLI / Codex / Qwen Code / OpenCode / GitHub Copilot CLI + відповідність постачальника #/config для кожного + «увійдіть перед продовженням» (відповідає розділу швидкого старту career-ops.org/docs; пояснює, що web-ui є автономною альтернативою, яка не потребує CLI). Новий tests/gemini-connector.test.mjs (8 сценаріїв) охоплює кожну гілку runGemini — без ключа, успіх, помилка API, порожнє/заблоковане завершення, некоректне тіло відповіді, тайм-аут, мережева помилка, hasGeminiKey — доводячи server/lib/gemini.mjs до 100% за інструкціями. Загальне покриття: 96% рядків / 88% гілок / 96% функцій. Набір тестів 1126 → 1134.
[1.74.0] — 2026-06-17
feat(llm): GitHub Models (Copilot) як 6-й провайдер + канонічне вирівнювання 6 асистентів. career-ops.org/docs перераховує шість ІІ-асистентів для написання коду — Claude Code, Gemini CLI, Codex, Qwen Code, OpenCode, GitHub Copilot CLI. Тепер web-ui підтримує всі шість: п’ять відповідають наявним активним провайдерам (Anthropic / Gemini / OpenAI / Qwen / OpenRouter), а GitHub Copilot CLI отримує виділений конектор GitHub Models — runGitHubModels (OpenAI-compatible; PAT GitHub з областю models), що налаштовується в #/config (GITHUB_MODELS_API_KEY + GITHUB_MODELS_MODEL) і вибирається через LLM_PROVIDER=github; 6-й у порядку auto. Пакети довідки та README тепер перераховують канонічні шість (перейменовано Qwen CLI→Qwen Code; додано Gemini CLI + GitHub Copilot CLI), а README додає повну таблицю посилань на режими та адаптери порталів на career-ops.org/docs, щоб кожна функція відстежувалась до батьківського проекту. tests/llm-provider-context.test.mjs розширює матрицю меж отримання до всіх шести провайдерів (cv.md + profile.yml вбудовані + повернутий артефакт); нові ключі GITHUB_MODELS_* додані до всіх 12 словників локалей. Набір тестів 1125 → 1126.
[1.73.0] — 2026-06-17
feat(llm): універсальний конектор Gemini + верифікований контекст CV/профілю для всіх провайдерів. Додано server/lib/gemini.mjs (runGemini) — клієнт Gemini generateContent без зовнішніх залежностей, що повертає ту саму форму {markdown, usage, error}, що й клієнти, сумісні з Anthropic / OpenAI. Виправлення: /api/mode/:slug і /api/deep раніше спрямовували промпти через gemini-eval.mjs, призначений виключно для оцінювання вакансій, через що Gemini Run live повертав оцінку замість запитаного артефакту (супровідний лист, аутрич, бриф). Тепер вони викликають runGemini з bundleProjectContext, тому cv.md + config/profile.yml вбудовуються інлайн для Gemini так само, як і для всіх інших провайдерів — листи та брифи є детальними й персоналізованими. Новий tests/llm-provider-context.test.mjs імітує HTTP-межу кожного провайдера та перевіряє, що всі п’ять (Anthropic / Gemini / OpenAI / Qwen / OpenRouter) вбудовують cv.md + profile.yml інлайн і повертають артефакт (матриця mode + deep + evaluate, 9 випадків). /api/evaluate зберігає свій gemini-eval.mjs, налаштований під вакансії. Suite 1116 → 1125.
[1.72.0] — 2026-06-17
feat(modes): Run live тепер повертає підсумковий артефакт безпосередньо (контракт виведення за один запит). Батьківські шаблони modes/<slug>.md написані для інтерактивних сесій Claude Code — деякі з них (cover, contacto та інші) роблять паузу, щоб задати уточнювальні запитання перед формуванням результату, через що Run live у вебінтерфейсі видавав анкету замість артефакту. buildModePrompt тепер огортає кожен режим у неінтерактивний контракт виведення: виконує аналіз (розбір вакансії, нотатки про компанію, ключові слова ATS, розбіжності профілю↔вакансії, вибір тону/подачі) у фоновому режимі, обирає розумні значення за замовчуванням із cv.md / config/profile.yml для всього, про що шаблон зазвичай питав, і виводить лише підсумковий артефакт — із завершальним нагадуванням для кожного режиму «output ONLY {the cover letter / outreach message / …}». Тепер клік на Run live у #/cover повертає саме супровідний лист; те саме виправлення застосовується до всіх загальних режимів (cover, contacto, interview-prep, project, training, followup, patterns) у всіх 12 локалях (артефакт створюється мовою інтерфейсу через директиву локалі). Suite 1103 → 1116.
[1.71.2] — 2026-06-17
docs(i18n): публікує прохід з узгодженості документації. Блок “Translations of this guide” у кожному README тепер містить усі 11 мов-«сестер» (раніше деякі пропускали English/Français або мали посилання на самих себе), а порожній рядок перед роздільником розділу відновлено. Повний QA-запит регресійного тестування перейменовано на поточну версію, а документацію (CLAUDE.md, CONVENTIONS, LOCALIZATION, PROJECT-CONTEXT) синхронізовано з поточною версією та кількістю тестів (1103). Жодних змін у коді чи поведінці — лише документація, тому переклади довідки/UI та всі функції версій 1.70.0–1.71.1 залишаються без змін.
[1.71.1] — 2026-06-17
fix(i18n): вбудований посібник із довідки тепер повністю перекладено всіма 12 мовами. Додано docs/help/{pl,uk,ar}.md (кожен містить перевірену структуру 19 H2 / 75 H3), завдяки чому #/help надає нативний пакет польською, українською та арабською мовами замість переходу на англійську — GET /api/help/{pl,uk,ar} тепер повертають власну локаль. Підключено до всіх перевірок довідки (help-ui, help.test, help-ru-config-section, canonical-docs-coverage). Також завершено всі списки перекладів на 12 мов: блок «Translations of this guide» у README (9 файлів README), заголовки «Translations:» у локалізованих CHANGELOG (8 файлів) та оновлено застарілі лічильники документації. Suite 1100 → 1103.
[1.71.0] — 2026-06-16
feat(cover): генерація PDF супровідного листа безпосередньо з #/cover. Режим cover (доданий у v1.70.0) формує текст листа; тепер у результаті з’являється кнопка Generate PDF, яка рендерить його через спільний вбудований конвеєр markdown→PDF (POST /api/stream/pdf/inline → generate-pdf.mjs) — той самий шлях, що використовує interview-prep. Тепер можна створити лист і надіслати PDF, не залишаючи SPA.
test/docs: посилення перевірки v1.70.0. Додано CI-ізольоване покриття для режиму cover (список дозволів + збірка промпту), перемикача <select> прапорів + арабського RTL (dirFor/<html dir>), top.langLabel у кожній локалі, підключення PDF супровідного листа, а також директиви локалі prompts.mjs + скаффолдингу для fr/pl/uk/ar. Оновлено застарілі посилання «всі 8» → 12 локалей у docs/sdd/CONVENTIONS.md і в промпті регресійного QA всього проєкту.
[1.70.0] — 2026-06-16
feat(i18n): три нові мови інтерфейсу — польська (pl), українська (uk) та арабська (ar, з повною підтримкою RTL) — розширюють SPA до 12 локалей, що відповідає всім мовам README батьківського проекту career-ops. Кожна нова локаль постачається з повним словником із 697 ключів (public/js/lib/locales/i18n-dict.{pl,uk,ar}.js), перевіреним наявними наборами тестів паритету / покриття / відсутності витоків латиниці / відсутності персональних даних. Арабська додає справжню підтримку письма справа наліво: i18n.js встановлює <html dir="rtl"> для RTL-локалей, а блок [dir="rtl"] в app.css відображає хром (бічна панель, ящик сповіщень, таблиці та блок-цитати markdown, вбудовані відступи) — LTR-локалі залишаються незмінними побайтово. Новий ключ top.langLabel (×12) іменує перемикач для програм читання з екрана.
feat(ui): випадаючий список <select> із піктограмами прапорів замінює ряд кнопок, що переносилися. При 12 локалях старий ряд .lang-btn переносився на три рядки в бічній панелі; нативний <select> (кожен пункт з префіксом у вигляді емодзі прапора) масштабується акуратно, підтримує клавіатуру та програми читання з екрана без додаткових налаштувань, а також є безпечним для CSP (обробник зміни через addEventListener, без вбудованого JS). Там, де платформа не має гліфів прапорів, вони замінюються літерами регіону, тому мовна мітка завжди є основним ідентифікатором.
feat(cover): перенесення режиму супровідного листа з батьківського проекту (career-ops v1.10.0 + вітання v1.11.0) до SPA. Нова сторінка #/cover у групі навігації «Заявки», побудована на базовому виконавці режимів: опис вакансії + компанія/роль + необов’язкове вітання → персоналізований лист, згенерований із cv.md / modes/_profile.md. Додано cover до серверного MODE_ALLOWLIST та блок i18n cover.* (×12 локалей).
chore(compat): відстеження батьківського career-ops v1.11.0. Підтверджено, що контракт читання/запису залишається чинним — data/applications.md й надалі є джерелом істини у форматі markdown (SQLite-індекс трекера у v1.11.0 є похідним кешем), стовпці трекера й надалі зіставляються за заголовком. parentVersion тепер повідомляє 1.11.0.
fix(i18n): усунення прихованої прогалини, де французька мова (додана у v1.61.0) була відсутня в LOCALE_NAMES та SCAFFOLD_STRINGS у server/lib/prompts.mjs — LLM-виклики французькою мовою мовчки переходили на англійський вивід та англійські шаблони. fr/pl/uk/ar тепер усі підключені до шляху локалі підказок.
Відомі подальші дії: вбудований довідковий посібник (
docs/help/) повертається до англійської для pl/uk/ar (сам UI-хром повністю локалізований); інтерактивне введення для співбесід батьківського проекту, зворотне виявлення ATS та новіші постачальники сканування ще не представлені в SPA.