Dziennik zmian
GitHubKażda istotna zmiana, wydanie po wydaniu. Ten sam plik jest dostępny w repozytorium i przetłumaczony na wszystkie 19 języków.
[1.253.0] — 2026-10-24
Dziesięć nowych źródeł ofert dołącza do skanera — Atlassian, BWI, Computrabajo, Dover, Google, Kalibrr, Magneto365, Platsbanken, Tech in Asia i Zoho Recruit — rejestr dostarcza teraz 120 źródeł (115 EN + 5 RU) z 115 adapterami, a role matcher rozdziela tytuły różniące się tylko krótkim kodem wielkimi literami.
Dodano
- 10 źródeł portowanych z rodzica 1.38.0, każde ze swoim adapterem fetch-walk i wyizolowaną CI-suitem (fałszywy fetchImpl, zero sieci): Atlassian (pojedynczy feed JSON bez auth, URL-e iCIMS, allowlist https+icims.com), BWI (ItemList JSON-LD, JSON.parse najpierw), Computrabajo (LATAM, dekodowanie encji, hiszpańskie „remoto” czytane jako remote), Dover (paginacja DRF per tenant, render
Remote (International), tablice walidowane UUID), Google Careers (pierwsze strony per fraza, pracodawca karty wygrywa, dedup między zapytaniami), Kalibrr (agregator SEA, id feedu jako id wiersza), Magneto365 (LATAM, stałe tempo między stronami), Platsbanken (szwedzkie API JobTech, okna per słowo kluczowe), Tech in Asia (klucze Algolia odkrywane z builda strony), Zoho Recruit (board hidden-input, ograniczone wzbogacanie detail, waluta tylko ISO-4217). - Licznik rejestru: 120 źródeł = 115 EN + 5 RU · 115 adapterów; pięć gate’ów liczników regenerowanych z żywego rejestru; fallback dropdownu
#/scan, linki cvstart.org i help §17 ×18 podążają.
Naprawiono
- role-matcher (port #5688): tytuły różniące się tylko krótkim kodem wielkimi literami („HR BP” vs „HR GP”, „AWS” vs „GCP”, także w mieszanych pismach) nie są już sklejane fuzz-matchem jako ta sama oferta; kody czytane są z surowego tytułu z wykluczeniem słów-szumów, a guard stoi tuż przed współczynnikiem Jaccarda.
- Porty przeżyły rewizję Opus 5-5 o maksymalnej surowości (21 ustaleń): throw na cicho-pustych tablicach przy dryfie markupu (google/bwi), przedwczesnie przerwany skan rzuca zamiast zwracać
[], kolejność decode-then-strip w scraperach LATAM (forma XSS strip-then-decode), https+allowlist na URL-ach wierszy atlassian, asercje hostów odrzucające porty, parse późnych stron wewnątrz try (partialie przeżywają) oraz uczciwość testów (budżety liczone dokładnie, kontrakty koercji przypięte prawdziwie). 13 ustaleń naprawionych; ogon [spec] śledzony osobno.
Uwagi
- Pięć RU pozostaje web-ui-only (brak adapterów upstream — celowo); każde źródło EN ma swój adapter.
- Ratchet pokrycia: sześć największych portów podniesionych do ≥95 % branch (27 nowych przypadków); reszta defensywnego martwego kodu udokumentowana per plik.
- Nowe źródła wybiera się przez
provider: <slug>w portals.yml — dla istniejących konfiguracji nic się nie zmienia.
[1.252.1] — 2026-10-17
Baner wersji w wiki jest teraz sprawdzany przez skrypt, a nie ręczny przegląd — regresja v1.252.0 wykryła go tylko ręcznie — a dyrektywa locale jawnie nadpisuje language.output profilu i język oferty.
Dodano
scripts/wiki-banner-check.mjs— brama, o którą prosiła regresja: czyta każdyHome*.mdw klonie wiki i porównuje baner zpackage.jsoni z ŻYWYMI licznikami rejestru (scanner adapters z rejestru portali — 105, a nie przeterminowane 109 z banera; route modules zserver/lib/routes/; UI locales z zestawu CHANGELOG). Regex banera jest agnostyczny językowo po KSZTAŁCIE: zlokalizowane strony Home tłumaczą etykietę i liczniki («Текущий релиз», «Aktuel udgivelse», «адаптеров сканера», «enhedstests»), a ich liczby uciekły dalej (5177) niż strona EN (5245).--tests Nprzyjmuje liczbę, którą właśnie wypisał świeżytest:ci;--check-onlyzakazuje niejawne klonowanie do użytku offline. Test fixtury offline wtests/wiki-banner-check.test.mjs.
Naprawiono
- Baner wiki Home ×18 znów jest w synchronizacji (idzie z tym wydaniem): przegląd v1.252.0 zmieniał badge’y i linki, ale nigdy linię banera, i nic mechanicznego tego nie flagowało. Brama powyżej czyni to blokującą kontrolą wydania.
- Dyrektywa locale ustala priorytet języka (
buildLocaleDirective): «This UI locale overrides the profile’slanguage.outputsetting and the job posting’s own language». Własna reguła 6 rodzica każe pisać wlanguage.output— bez zdania o priorytecie model rozwiązywał dwa sprzeczne polecenia niespójnie per locale, co było rozrzutem kolumny języka w v1.252.0. Przypięte przeztests/locale-directive-language-output.test.mjsna tekście dyrektywy (17 lokali nie-EN + pusty EN).
Uwagi
- Obserwacja FORMY w ta evaluate (§3, pilnować): pierwszy żywy przebieg v1.252.0 dał evaluate na 48 336 znaków bez Block G i bez SCORE_SUMMARY — kształt pętli, nie języka (CAR-70 dotyczy języka). Powtórzy się w następnym wydaniu — osobne zadanie w Linear, obok CAR-70.
- Zgodnie z FIX-PROMPT: rodzic zostaje read-only; nadpisanie mieszka wyłącznie w dyrektywie UI.
[1.252.0] — 2026-10-17
Fork rodzica jest zsynchronizowany z career-ops-hq/career-ops — 264 commity upstream, rodzic 1.36.0 → 1.37.0 — obie dywergencje forka obronione, a wdrożenie przypina działającego rodzica z powrotem do tej bazy.
Dodano
- Wietnamski (vi) tryb rynkowy z upstream (
modes/vi/,tuyen-dung/ung-tuyen): BHXH/BHYT/BHTN, thử việc, lương tháng 13, trợ cấp thôi việc — 21. rynek w tabeli trybów rodzica. - Dostawca tablicy Tech in Asia (upstream): czyta publiczny indeks Algolia
job_postings, o który sam pyta UI ofert techinasia.com — SEA-owa tablica startupów, ~300 żywych ofert przy próbkowaniu, 273 z nich indonezyjskie. Klucze są odkrywane na nowo przy każdym przebiegu z builda strony, własny link aplikacji pracodawcy wygrywa ze stroną tablicy, a wynagrodzenie celowo nie jest przyczepiane (pola wynagrodzeń w indeksie to flagi, nie kwoty). - Osiem nowych dokumentów sygnałów legitymizacji ofert Block G (
modes/oferta-signals/08–17): kraj w terminologii benefitów, tag lokalizacji platformy zewnętrznej, licencjonowanie agencji, nadmiar wymogów migracyjnych, treści zakazane w jurysdykcji, szerokość widełek pay-transparency, pytanie prawnika o płacę minimalną, ujawnienie AI-screeningu, ujawnienie umowy na czas określony, siła nabywcza przy relokacji.
Zmieniono
- Usztywnienia po stronie rodzica, które jadą z bazą: sprawdzenie story-provenance działa per jednostka i zdanie i trzyma liczby
user-cannot-confirmpoza negocjacjami, ATS i wyjściem interview; fact-gate CV odpala się na każdym renderze i czyta przeformułowane i ustrukturyzowane twierdzenia; LaTeX odrzuca przedawnione wyciągnięte sloty przed zapisem; przemiatanie launchd follow-ups jest pomijane, gdy follow-ups są wyłączone; update-system trzyma skan lokalnych edycji w limicie argv. - Dywergencje forka przeżyły merge:
providers/telegram.mjs(parser wyłącznie forka, ADR-0001) i Unicode lookaroundLOCATIONISH_REwtelegram-channel.mjs(ADR-0002). Dokument tablic wymienia teraz ulepszony wiersztelegram-channelz upstream, wiersztelegramwyłącznie forka, Tech in Asia i domyślnymax_pagesTencent podniesiony 20 → 100.
Uwagi
- Brak zmian zachowania SPA w tym wydaniu: to pociąg dokumentacyjny plus przypięcie rodzica na nowo. Wdrożenie działa teraz na rodzicu 1.37.0; tabela statusów kanonicznych nie jest dotykana przez deltę rodzica — statusy trackera renderują się jak dawniej.
- W merge’u upstream rozwiązano dwa konflikty:
docs/SUPPORTED_JOB_BOARDS.md(oba wiersze telegram zachowane) itest-all.mjs(oparty na walkTreecopyDirSyncz upstream subsumuje ręczny guard zagnieżdżonych checkoutów po.gitz forka; lista importu to suma).
[1.251.1] — 2026-10-12
Filtr specjalizacji dopasowuje teraz tylko WYRÓŻNIAJĄCE słowa roli — staż i ogólne rzeczowniki stanowiskowe nie dopasowują już oferty same z siebie — a remote-qa oddziela kształt od języka, więc dryf nie czerwieni A–G.
Naprawiono
- Filtr specjalizacji wyrzuca staż i ogólne rzeczowniki ze swojego matchera: «Senior PHP Developer» dopasowywał «Senior Java Developer» przez wspólny Senior/Developer. Matcher zachowuje tylko wyróżniające tokeny (PHP, Go, Platform, SRE, Backend…); rola bez wyróżniających tokenów («Software Engineer») spada na dopasowanie całej frazy. Granice słów zostają: «Go» nigdy nie dopasuje «Golang» ani «Google».
- remote-qa oddziela kształt od języka: flaga A–G oceniana tylko po kodach bloków/SCORE_SUMMARY/looping; dryf
report not in <locale>trafia do własnej flagi i kolumny warnings (tabela zyskuje brakującą 4. kolumnę; kody zapisywane per wiersz). - Pasek mapy to prawdziwe 50/50 przy 390 px (podział 58/42 zostawiał wyszukiwarkę na 124 px i ucinał placeholder), martwa reguła CSS
.job-map-job-selectusunięta. - CodeQL 552 — nieużywana zmienna
OVERLAYSw teście design-qa usunięta.
Uwagi
- Mile wciąż odkłada właściciel. Dryf języka ta pozostaje UDOKUMENTOWANYM ograniczeniem backendu hermes (2–26 % prozy między przebiegami; A–G się trzyma): remote-qa zgłasza to jako oczekiwane znalezisko. Lista tokenów ogólnych jest celowo minimalna — rozszerzenie to jedna linijka na język.
[1.251.0] — 2026-10-12
Select mapy filtruje teraz według SPECJALIZACJI z ustawień (config/profile.yml → target_roles.primary): wybierz «Product Manager» lub «Backend Engineer (Go / PHP)», a mapa zachowa tylko oferty, których tytuł niesie słowa tej roli. Lokalizator listy ofert z v1.250.0 usunięto — to było złe narzędzie (korekta właściciela).
Dodano
- Filtr specjalizacji: select wyświetla specjalizacje z ustawień (target_roles.primary); wybranie zachowuje tylko oferty, których tytuł niesie jeden z wyróżniających tokenów roli (granice słów, bez wielkości liter — «Go» nigdy nie matchuje «Google»); Reset przywraca wszystkie.
- Lokalizator listy ofert z v1.250.0 usunięty — zamiennik: filtr specjalizacji, nie lista ofert (korekta właściciela).
Zmieniono
- Two mobile-map height specs: the floor moves 600 -> 540 px (the toolbar takes ~90 px of the viewport).
Uwagi
- Mile wciąż odkłada właściciel. Dopasowanie celowo TYLKO po tytule słowami z ustawień: firmy czy opisy wciągnęłyby do specjalizacji niepowiązane oferty. Oferta spoza skonfigurowanych ról pozostaje widoczna przy «All».
[1.250.0] — 2026-10-12
Strona mapy staje się użyteczna: lokalizator ofert nad mapą przenosi do dowolnej widocznej oferty i otwiera jej podgląd (również na desktopie), a wyszukiwanie tekstowe zawęża mapę po firmie lub stanowisku — oba przetrwają odświeżenie.
Dodano
- Lokalizator ofert: select nad mapą wyświetla widoczne (po filtrach) oferty posortowane po firmie+stanowisku; wybranie przenosi do kółka i otwiera podgląd — także na desktopie.
- Wyszukiwanie tekstowe: zawęża mapę po podciągu firma+stanowisko (porównanie bez wielkości liter; pole zachowuje wpisaną wielkość), trwa w map-prefs, Reset czyści.
- FAB nie zasłania atrybucji na
#/mapna wszystkich szerokościach.
Naprawiono
- Dwa specy wysokości mobilnej: próg spada do 540 px (pasek zajmuje ~90 px viewportu).
Uwagi
- Mile właściciel odkłada na następny release. 4 nowe klucze i18n wchodzą do 18 słowników, złożona migawka jest regenerowana. Lokalizator zawsze otwiera podgląd (nawigacja zniweczyłaby jego cel); kółko znajduje się przez odwrotne odwołanie __job — NIE _point, który L.Circle już posiada.
[1.249.0] — 2026-10-11
Mapa ofert stawia teraz trafność na pierwszym miejscu: spokojna skala morski→szary wyróżnia najlepsze oferty, filtry oceny i dojazdu są zapamiętywane, telefon otrzymuje mapę na całą dostępną wysokość z podglądem po dotknięciu, a tracker współdzieli filtr i sortowanie dojazdu.
[1.248.8] — 2026-10-11
Paritet z rodzicem: fork i web-ui synchronizują się ze 115-commitowym delta upstream — nowe źródło PageUp, komórki URL trackera parsowane jako linki markdown, stan Assessment — plus praca językowa ta/ja: zapętlone raporty są ucinane i nazywane, szkielet nagłówków utrzymuje A–G stabilne, a udział pisma liczy się tylko z prozy.
Dodano
Naprawiono
- Nowe źródło PageUp (105 adapterów EN / 110 źródeł); komórki URL trackera parsowane jako linki markdown (href to klucz deduplikacji); stan Assessment przychodzi przez states.yml.
- Zapętlony raport jest ucinany i nazywany (
report looping (block B repeated)), szkielet nagłówków## A) … ## G)dla nieangielskich. - Udział pisma liczy tylko prozę (tabele, SCORE_SUMMARY, kod i URL wyłączone) — japoński raport z łacińskimi tabelami już nie faluje.
- /api/evaluate ostrzega
report not in <locale>, a remote-qa drukuje kody w kolumnie.
-
[1.248.7] — 2026-10-11
Rola z nagłówka raportu czyta teraz rzeczywistą konwencję rodzica — # Evaluation: {Company} — {Role} — zamiast zakładać # <Rola> — <Firma>, więc tracker nie niesie już «Evaluation:
Naprawiono
- Zlokalizowana etykieta jest zdejmowana najpierw (
Evaluation:,Оценка вакансии:i 16 wariantów); po etykiecieCompany — Role→ rola to prawa strona; bez etykietyRole — Company→ lewa; część nazywającą firmę decyduje; rola nigdy nie jest firmą ani słowem etykiety — zapasem jest czyszczona linia posta. - cleanup-plan sumuje N z linii (
— N dirty-URL line(s)), nie liczy plików — plik z 5 brudnymi URL dawał 1, nie 5. - Raport w złym języku ostrzega: prompt otwiera SIĘ i zamyka obowiązkową instrukcją języka (cały raport, tabele włącznie), a pipeline sprawdza język zapisanego raportu — dryf pojawia się jako ostrzeżenie
report not in <locale>. - Bez paplaniny modelu przed H1 — raport zaczyna się od swojej linii nagłówka.
Uwagi
- Nie przeniesiono i nie dotykano (zweryfikowano w regresji v1.248.6): embed-fetch, struktura linii posta («Компания : X»), deduplikacja «## Rejected», odrzucenie korzenia domeny przed fetch, uczciwość recon/link-check i tryby cleanup. Walidacja języka to ostrzeżenie — raport (już zwalidowany A–G + wynik) zapisuje się; operator widzi dryf i może powtórzyć ocenę.
[1.248.6] — 2026-10-10
Szlif po regresji łańcucha Telegram: rzeczywisty post zachowuje strukturę linii (etykieta «Компания : X» i linia roli są znajdywane tam, gdzie faktycznie są), rola w trackerze pochodzi z nagłówka raportu, a nie z surowej linii posta, a powierzchnie operacyjne (recon, cleanup-plan, link-check) raportują to, co deklarują.
Naprawiono
- Post z t.me nie skleja się już w jedną linię:
<br>staje się nową linią przed zdjęciem tagów, a numeryczne encje HTML są dekodowane; wzorzec etykiety firmy akceptuje formę ze spacją przed dwukropkiem. - Rola w trackerze pochodzi z nagłówka raportu (H1
# <Rola> — <Firma>); linia zapasowa jest czyszczona — bez hashtagów, bez emoji, ≤80 znaków. ## Rejectednie duplikuje się już: sekcja jest tworzona raz; każde odrzucenie dopisuje w niej swoją linię.- Korzeń domeny jest odrzucany przed żądaniem — śmieciowy URL nie kosztuje już nic.
- Recon wylicza sygnał kontraktu zamiast go deklarować (
honours rejected:sprawdzamarkPipelineRejectedwe wdrożonym kodzie); licznik znaczników nie drukuje już «0» dwukrotnie. - cleanup-plan raportuje liczby per kategoria (t-role do przeniesienia, linie dirty-URL, linie test-row) zamiast pojedynczego
grep -c, który liczył własną linię sukcesu. - link-check traktuje 5xx z github.com jako niezweryfikowane — za murem botów, nie jako zepsute linki.
Uwagi
- Nie przeniesiono i nie dotykano (zweryfikowano w regresji v1.248.5): sam embed-fetch, kontrakt pomijania pipeline, testy offline _setLookup, akceptacja porządkowych uk, granice słów w filtrze roli oraz tryb cleanup-apply. Liczenie per kategoria w cleanup-plan czyta etykiety wyjściowe samego skryptu — zmiana ich nazw po cichu zepsułaby liczniki.
[1.248.5] — 2026-10-10
Utrwalenie po regresji: pojedyncze wpisy t.me teraz pobierają sam tekst posta (forma embed), odrzucony wpis opuszcza pulę licznika ewaluacji po stronie serwera, a natywna numeracja bloków w ukraińskim raporcie jest akceptowana — do tego jeden test, który potajemnie korzystał z żywej sieci, na zawsze przechodzi offline.
Naprawiono
- Wpisy t.me w końcu są oceniane: strona pojedynczego posta serwuje w czystym HTML tylko nagłówek kanału (~0,2 KB — «View in Telegram» i nic więcej), model otrzymywał pusty opis i każdy wpis z Telegrama umierał na etapie oceny. Pobieranie teraz przepisuje
t.me/<kanał>/<id>(i formę feedut.me/s/…) na formę embed (?embed=1&mode=tme) — ten sam host, walidacja SSRF bez zmian — i czyta posta z.tgme_widget_message_text(fallback:og:description). Brak tekstu widżetu → odrzucenie na etapie pobierania (telegram post has no text,rejected: true) przed wydaniem tokenów LLM. - Licznik ewaluacji przestaje ponownie płacić za odrzucone wpisy (kontrakt po stronie serwera): odrzucony wpis jest teraz oznaczany w
data/pipeline.md— jego linia opuszcza ogrodzenie URL-i i trafia do sekcji## Rejectedz krótkim powodem (idempotentne, nigdy nie zduplikowane). Licznik pobiera gołe URL-e z ogrodzenia, więc oznaczony wpis jest naturalnie pomijany — bez zależności od wnętrza skryptu licznika. Recon wypisujepipeline rejected marks: N+honours rejected: yes (server-side)zamiast przeszukiwać skrypt. - Ukraińskie raporty ponownie przechodzą walidację A–G: model uk numeruje bloki według kolejności własnego alfabetu (А Б В Г Д Є Ж), a przejście podobnych znaków liczyło tylko А/В/Е — dokładnie bloki C, D, F, G brakowały na produkcji (2/2 reprodukcje). Walidator teraz akceptuje ukraińską sekwencję porządkową, gdy nagłówki pojawiają się w kolejności (ta sama dyscyplina co abjad dla ar i dewanagari dla hi), a prompt ewaluacji dla każdego locale teraz wyraźnie wymaga łacińskich
A–G. - Bramka słów kluczowych roli działa na słowa, nie podciągi: korzenie
linkedin.com/ix.com/przechodziły bramkę, bolead/itżyły w tekście interfejsu strony. Słowa kluczowe dopasowują się teraz na granicach słów Unicode, a korzeń domeny (URL bez ścieżki) jest odrzucany przed wywołaniem LLM. - Test jednostkowy nie potrzebuje już żywej sieci: test no-hints (
tests/auto-pipeline-jd-gate.test.mjs) podmieniał transport HTTP, ale nadal wykonywał prawdziwe zapytanie DNS — zielony w CI tylko dlatego, że runner miał łączność. safe-fetch zyskał hook_setLookup()(sam resolver jest wymienny w testach; kod produkcyjny nigdy go nie nadpisuje), a test rozwiązuje offline.
Dodano
- Tryby workflow
cleanup-plan/cleanup-applyw deploy.yml: produkcyjne czyszczenie śmieci QA (post-qa-cleanup) uruchamia się po stronie serwera bez SSH z laptopa. Log zawiera tylko liczby — bez nazw plików ani podglądów linii, bo log jest publiczny, a nazwy plików zawierają nazwy firm. Krok Verify jest pomijany dla trybów czyszczenia.
Uwagi
- Nie przeniesiono: kompilator lokalizacji po granicach słów i tabela stanów USPS z rodzica (udokumentowane od v1.248.1). Kontrakt pomijania odrzuconych wpisów żyje po stronie serwera (oznaczanie w data/pipeline.md), a nie w skrypcie licznika — ten jest poza repozytorium i celowo niezmieniany.
[1.248.4] — 2026-10-10
Łańcuch rozpoznawania roli dla wpisów z Telegrama: cyrylicki post z prawdziwą ofertą daje teraz nazwany raport zamiast odrzuconego pliku unknown-role — a wywołanie LLM następuje tylko dla wpisów warte oceny.
Naprawiono
- Łańcuch roli działa dla postów cyrylickich: lista słów kluczowych zyskała developer/programist/инженер/аналитик/менеджер/руководитель/timlid/lid/designer/tester/QA/architect/specialist/director/DevOps/SRE (stara była tylko EN: 0 z 40 prawdziwych postów otrzymywało rolę), konsultowany jest nagłówek raportu (
parseReportHeader— model pisze rolę w H1), a pierwsza sensowna linia posta to ostatnia deska ratunku. - Brama tożsamości przeniosła się PRZED wywołanie LLM: wpis bez firmy i bez śladu roli pada już na kroku fetch (
rejected: true) — bez palenia tokenów na ocenę, która i tak zostałaby odrzucona. t.me/s/<kanał>/<id>nie nazywa już firmy „S” — segment podglądu jest pomijany; obie formy linku rozwiązywane do kanału.- Samoopis „Компания: X” w postach Telegrama jest honorowany (i „…в компании X” w środku zdania dla hostów komunikatorów).
Dodano
- Porażki auto-pipeline niosą
rejected: truew błędzie SSE — serwerowy timer ocen używa flagi, by pominąć wpis pipeline zamiast ponawiać go co 2 godziny.
Uwagi
- Nie portowano: kompilator słów lokalizacji z granicami słów i tabela USPS (udokumentowane od v1.248.1).
- Blok „Translations” w README jest generowany z jednej kanonicznej listy, z testem paritetu w CI (17 linków na plik, własny nigdy nie linkowany) — ar/pl/uk zyskały blok; dryf separatorów
|/·wyeliminowany.
[1.248.3] — 2026-10-10
Kontynuacja rundy regresji: timer ocen nie może już pod żadnym pozorem archiwizować bezimiennych śmieci z Telegrama, czyszczenie QA nie usuwa już prawdziwych ofert, atrybucja mapy jest znowu widoczna, a chipy panelu czytają ≥ 4.5:1.
Naprawiono
- Auto-pipeline waliduje PRZED zapisem: raport bez wyniku 0–5 lub bez bloków A–G kończy bieg na kroku evaluate (
rejected: truew ładunku SSE) — bez pliku raportu, bez wiersza trackera. Wpisy t.me, które przechodziły bramę długości v1.248.2, dały po tamtej wersji dwa kolejne śmieci; teraz wpisy bez nazwy są odrzucane zcompany/role not identifiable. guessCompanyRolenie wymyśla już firmy z hostów komunikatorów —t.me,telegram.me,vk.com,linkedin.comi podobne są w EMPTY_DOMAINS: post Telegrama cofa się do nazwy kanału, a bezimienny wpis jest odrzucany zamiast trafić do archiwum jakounknown-role.post-qa-cleanupczyta najpierw wynik z nagłówka: auto-pipeline wycina blok SCORE_SUMMARY przed zapisem, więc stara kontrola tylko-summary oznaczała każdą zapisaną ofertę Telegrama jako śmieć — na produkcji 8 z 41 nosi wynik w nagłówku i--applyskasowałby je. Wynik z nagłówka (przezparseReportHeader) to teraz sygnał pierwotny; blok jest rezerwą. Dry-run drukuje powód dla każdego pliku.- Atrybucja Leaflet jest widoczna na #/map — docs-FAB ją zasłaniał (naruszenie licencji OSM); róg podniesiono o 96px.
- Chipу panelu osiągają 4.5:1 — etykiety
dash-chipi wariant--manualprzeszły na--foggy-strong(wcześniej 4.31:1).
Dodano
- Porażki auto-pipeline niosą
rejected: truew błędzie SSE — serwerowy timer ocen używa flagi, by pominąć wpis pipeline zamiast ponawiać go co 2 godziny.
Uwagi
- Dryf ar/ja nie powtórzył się przy ponownym uruchomieniu (patrz v1.248.2).
- Czyszczenie produkcji wciąż czeka na wyraźne „tak” (CAR-61c); z tą poprawką czyszczenie nie może już usunąć prawdziwych ofert Telegrama.
[1.248.2] — 2026-10-10
Runda regresji: timer ocen nie zamienia już śmieci z pipeline w „Last evaluation”, parsowanie SCORE przeżywa realne formaty, a tracker wreszcie mówi Twoim językiem.
Naprawiono
- Raporty z pustym JD nie są już zapisywane. Brama JD auto-pipeline podniosła się z 50 do 200 znaków przed wywołaniem LLM — strony-placeholdery (
example.com/qa-v167-…) kończą się błędem SSE + ostrzeżeniem w konsoli zamiast raportu…-t-role-<ts>.md, który panel pokazywał jako „Last evaluation” (42 takie pliki na produkcji). - Parsowanie SCORE_SUMMARY przeżywa realne formaty: „4,2/5”, „4.2 / 5”, „4.2”, „SCORE :” — wszystko przechodzi; przecinek z 1–2 cyframi to dziesiętne, z 3 to tysiące (stary kod czytał „4,200” jako 4.2 i przepuszczał bramę 0–5). Niepowodzenie loguje wyłącznie linię
SCORE:— nigdy treść raportu (logi CI są publiczne). - Statusy trackera są przetłumaczone: zakładki i odznaki pokazują zlokalizowane etykiety we wszystkich 18 locale; kanoniczna wartość w danych, filtrach i URL nietknięta.
- Uczciwy ETA: „⏱ ~30s” stał się „~2–4 min” w evaluate/advisor/raporcie rynkowym (realny zakres 86–285 s), a podtytuł evaluate czyta A–G.
- Dostępność: licznik API-keys w config i licznik pipeline przekraczają 4.5:1 (wcześniej 4.31:1); chip fasetu z pustą wartością nie renderuje się już bez dostępnej nazwy.
- Polerowanie UI: Delete zapisanych wyszukiwań wygląda destrukcyjnie tylko przy wybranym wyszukiwaniu (inaczej disabled); karta EMAIL profilu nie obcina się przy 1440 px; pigułka live-evals zyskała odstęp ikona/tekst także w RTL; docs-FAB nie zasłania atrybucji Leaflet; „?” help nie łamie się pod zakładkami stats; usage zyskało oddech między podtytułem a zakładkami; health mówi teraz career-ops-ui
Dodano
scripts/post-qa-cleanup.mjs: domyślnie dry-run,--applyz automatycznymi kopiami zapasowymi (*.bak-<ts>, raporty przenoszone doqa/cleanup-backup-<ts>/): wiersze ZZ-QA-TEST trackera, raporty*-t-role-*bez ważnego SCORE, wpisyexample.comw pipeline.
Uwagi
- Dryf ar/ja z rundy regresji nie powtórzył się przy ponownym uruchomieniu (oba: lang ✓ + A–G ✓) — wpis ta w language-check i utwardzony parser SCORE wchodzą jako defense-in-depth.
- Czyszczenie produkcji czeka na wyraźne „tak” użytkownika: najpierw plan dry-run, potem
--apply
[1.248.1] — 2026-10-09
location_filter zyskuje rodzicielskie poziomy always_allow i block_hard (CAR-60) — wielokrajowy ciąg lokalizacji przeżywa listę zablokowanych, a jawna twarda blokada nie da się już uratować.
Naprawiono
always_allowbijeblock: przyblock: [romania, poland, croatia]ialways_allow: [united kingdom]scalona komórka workable „London, United Kingdom · Romania · Poland · Croatia” przechodzi — region macierzysty jest opcją (przypadek konsumencki workable #4806, teraz w formie rodzica).block_hardbijealways_allow: terminy poziomu kraju, które nigdy nie mogą być uratowane trafieniem always_allow gdziekolwiek w ciągu.strict: trueliczy terazblock_hardjako poziom restrykcyjny; sekcjalocation_filterw docs/help dokumentuje oba poziomy ×18.
Uwagi
- Świadomie nieportowane tym razem: rodzicielski kompilator słów kluczowych lokalizacji z granicami słów i jego tabela stanów USPS (web-ui trzyma dopasowanie substring; tabela służy konfiguracjom US-centrycznym — odłóż pod CAR-60, gdyby była potrzebna). Przejściowa forma allow-list testu konsumenckiego workable zostaje jako drugi werdykt obok nowej, rodzicielskiej.
[1.248.0] — 2026-10-09
Paritet z rodzicem: pięć poprawek dostawców/liveness przeniesionych — tablice, które przeniosły API, dalej działają, a baner zamknięcia w osobnej linii nie umyka.
Naprawiono
- Gupy podąża za API na
portal.gupy.ioi wysyła nazwy filtrów, które API faktycznie czyta (workplaceType/type) — stare liczby mnogie były po cichu ignorowane;countrynie jest już wysyłane (skonfigurowany kraj rysuje ostrzeżenie z nazwą wpisu). Poufni pracodawcy wypadają przy dokładnym dopasowaniu etykiety („Confidencial Seguros” przeżywa), amax_pagesma sufit 100 — API odpowiada 400 po offsecie 10 000, a ostrzeżenie o obcięciu doradza zawężenie słów kluczowych. - Workable zachowuje wszystkie kraje oferty wielokrajowej: rodzeństwo pod tym samym URL-em zadania składa się w jeden wiersz („London, United Kingdom · Romania · Poland · Croatia”) zamiast wygrywać pierwszy kraj.
- Liveness: baner w osobnej linii nie jest częścią linii powyżej — „Sign in if you want to apply” / „Get notified when this position is filled” pod ofertą czyta się jako klauzulę zamknięcia, a prawdziwe „until filled” przez linie nadal czyta aktywne.
- Radancy czyta elementy-rodzeństwo
job-locationw legacy-markupie kart (układy rodziny Barclays kładą lokalizację po</a>) — wiersze bez własnej lokalizacji zostają puste zamiast pożyczać sąsiada. - Fallbackowe linki SmartRecruiters zachowują skonfigurowany slug — oferta bez zaufanego
refsyntetyzuje publiczny URL ze sluga tenanta, nigdy z nazwy wyświetlanej.
Dodano
- No-porty udokumentowane: nadrzędna poprawka
_httpproxyfetchImpl(web-ui nie ma gałęzi proxy — port unieważniłby sprawdzanie tożsamości straży DNS-rebinding i dodał zależność undici, której repo świadomie unika); nadrzędneverify-ats(+226 linii) icv-facts(web-ui ma własny scoring ATS i parsowanie CV); nadrzędny dashboard Go TUI i skrypty CLI; przestawienie importów w Teamtailor (kosmetyka).
Uwagi
- Znana luka jako follow-up: tier
always_allownadrzędnego filtra lokalizacji (test konsumencki workable przeżywa dzięki niemu blok UK) nie istnieje w web-ui; port wyraził ten sam werdykt konsumenta testem allow-list. Zapisane jako osobna zmiana.
[1.247.0] — 2026-10-09
Ogon przeglądu senior-design CAR-49…58 domknięty — wszystkie pozostałe minor/polish oraz ciemna mapa, którą poprzednie wydanie celowo odłożyło.
Naprawiono
- Mapa renderuje prawdziwy ciemny motyw. Zoom/warstwy/atrybucja ściemniały w v1.246.0; teraz podążają też kafle: tryb ciemny rysuje warstwę OSM z CSS-ową inwersją (bez kluczy dostawcy), a keyed preset Carto-dark jest dostępny przez
MAP_TILE_DARK_URL(jego host dopuszczony w CSPimg-src). Warstwa przemontowuje się na żywo przy zmianie motywu. - Żółte callouty mają warianty ciemne (
config,batch, ostrzeżenie hero) przez mechanikę tokenów z v1.246.0 — i przy okazji złapany regres:.callout aprzygważdżał.btn-primary; teraz w zakresie:not(.btn). - URL na karcie info Apply nie ucina się już w połowie słowa.
- Przyciski nagłówka CV to jeden system ikon (tekst; mix 📁/📄/💾 zniknął).
- Zakładki statusów trackera w jednym repertuarze wielkości liter — sentence case z lokalnymi niuansami (CJK/ar/hi/ta bez form rodzajowych).
- Ikony topbara to jeden zestaw stroke-SVG — mix 🔔/🌙/🩺 zniknął; przycisk motywu rysuje słońce/księżyc przez CSS.
- Karta Pipeline na dashboardzie traci różowe wyróżnienie (pierścień tylko hover/focus).
- Usuwanie zapisanych wyszukiwań wygląda destrukcyjnie (
.btn-danger, nie neutralny ghost). - Podgląd pipeline ma prawdziwy stan pusty (tytuł + podpowiedź + CTA, wzór trackera).
- Meta czasu/kosztu to jeden wzorzec:
UI.pageMetarysuje ⏱ + koszt w jednej linii pod tytułem widoku (evaluate/deep/auto/mode-page/orientation). - Auto-pipeline traci ✨ — jedyny dekorowany h1 wraca na wspólną lewą krawędź.
- URL docs w batch to inline-link.
- interview-digest / orientation mają zaprojektowane stany puste (tytuł + podpowiedź + CTA).
- Export career-plan jest wyłączony bez planu, akcje w jednym rzędzie.
- stats: zniknął zduplikowany nagłówek „Market report”, a placeholder regionu się mieści (krótszy tekst ×18, stała szerokość).
- Config nie wycieka już absolutnych ścieżek — serwerowy
displayPath()pokazuje~/…lub samą nazwę pliku. - Helper LLM_PROVIDER to trzy krótkie linie (×18 +
pre-line), nie 150-znakowy mono-mur. - Karta EMAIL profilu trzyma adres w jednej linii (ellipsis; zawijanie tylko ≤480px).
- Tekst Health nie łamie już słów („Run buttons” w całości; overflow-wrap anywhere).
- Inline-code w helpu przeżywa RTL (izolacja LTR, nowrap, przewijalne).
- Pigułka „Live evals” w hero nie koliduje już w ru/ar (flex-wrap, nieskurczalne ikony).
Dodano
- Preset ciemnych kafli (
MAP_TILE_DARK_URL+ atrybucja) udokumentowany w kodzie; rozszerzenie CSPimg-srcobejmuje host Carto.
Uwagi
- Domyślne ciemne kafle to CSS-owa inwersja OSM — Carto bez klucza zamknął basemapy za API key (zweryfikowane zapytaniem); keyed preset to opt-in, nie domyślne.
[1.246.0] — 2026-10-09
Wszystkich dziesięć czołowych ustaleń przeglądu senior-design CAR-48 naprawiono — łącznie z blockerem i wszystkimi siedmioma major.
Naprawiono
- Apply w ciemnym motywie: link na karcie info jest znowu widoczny. Karta trzymała jasną powierzchnię w ciemnym motywie; link „Need Playwright? See …” miał ≈1.0:1. Theme-aware
.callout--info(tokeny surface/border/text/link) podnosi ciemny link do ≈7.3:1. - RTL nie odwraca już kompozycji liczbowych. Pigułki wyniku („1.5 / 5”), pasy raportów („≥ 4.5”, „< 3.5”) i dashboardowe „/ 5.0” dostają izolację kierunkową (spany LTR); słownik ar przeformułowuje zakresy słowami tam, gdzie proza tego chce.
- Markdown CV pozostaje LTR. Textarea i podgląd renderują się z
dir="ltr"po arabsku; otoczka pozostaje RTL. - Kolumna DATE raportów nigdy więcej nie łamie daty ISO (nowrap + cyfry tabelaryczne).
- Sidebar kończy się nad HUD-em użycia (rezerwa scrollportu + fade) — ostatni element nawigacji nie zjeżdża już pod panel; z lustrzaną obsługą RTL.
- Skan mobilny @390: „Save search” w pełni widoczny — rząd kontrolek się zawija i ściska zamiast ucinać się na krawędzi.
- Kontrolki mapy podążają za ciemnym motywem (zoom, warstwy, atrybucja). Kafle celowo bez zmian: ich origin jest przypięty serwerowo przez CSP
img-src. - FAB czatu nie zasłania już interaktywnych treści — padding przewijania go omija (przyciski Disable w Portals, pigułka wyniku w Reports, input two-pager, atrybucja Leaflet).
- Dziennik aktywności mówi językiem interfejsu: 22 slugów akcji zlokalizowanych ×18 locale (z fallbackiem na surowy id dla nieznanych) i przetłumaczone chipy filtrów; kolumna TARGET zostaje — wypełnia ją auto-pipeline.
- Formularze assessments mają prawdziwe etykiety (sentence case, powiązanie
htmlFor/id) zamiast samych placeholderów.
Uwagi
- Poza tym wydaniem: ciemne kafle mapy (wymaga rozszerzenia CSP
img-src— zmiana serwerowa, celowo nie po stronie klienta); ciemne warianty żółtych calloutów (config,batch) — mechanika tokenów gotowa na kontynuację.
[1.245.0] — 2026-10-09
Tamilski (தமிழ்) dołącza jako 18. język interfejsu — pierwszy nowy język od fali 17 lokalizacji, z pełną parnością kluczy.
Dodano
- Tamilski (
ta): 1449/1449 kluczy w pełnej parności zen, zero zgubionych placeholderów, konwencje indic-tech w stylu hi (dostawcy, modele, ścieżki i polecenia zostają w alfabecie łacińskim).detect()przyjmujeta,ta-IN,ta-LK; tamilski jest LTR (zabezpieczone testem). - Pełny docs/help/ta.md (33 H2 / 125 H3, liczniki źródeł zweryfikowane z żywym rejestrem, kotwice canary Hermes, dosłowny YAML), plus lustra README.ta.md i CHANGELOG.ta.md.
- Bramy wyliczeniowe 17 → 18: LANGS, sondy detect, audyt i18n, parność changelogów, strażnik RTL,
langsw CI — przy okazji łapiehi, wcześniej nieobecne na liście CI.
Uwagi
- Landing cvstart.org pozostaje na razie przy 17 językach — tłumaczenie to osobne zadanie; sync treści strony już dostarcza docs/help/ta.md i changelog ta.
- REPORT_LABELS w
report-header.jszostaje przy 17 — parsowanie tamilskich raportów przyjdzie wraz z generowaniem tamilskich raportów w repo nadrzędnym.
[1.244.2] — 2026-10-08
Polerowanie strony skanowania: launcher, pasek statusu, panel repostów i filtry zaprojektowane jako spójny chrome — a tabela wyników nie może już być rozciągana przez dane boardów.
Naprawiono
- Komórki wynagrodzenia pokazują tylko zakres kwot. Niektóre boardy wkładają cały opis benefitów do pola wynagrodzenia — widoczna komórka pokazuje teraz tylko część kwotową, a tekst trafia do tooltipa (wcześniej: 6-wierszowa komórka rozciągająca każdy wiersz).
- Wiersze z pustym tytułem pokazują firmę (potem neutralny myślnik) zamiast gigantycznej pustej komórki.
- Badge seniority nigdy nie łamie się w swojej kolumnie o stałej szerokości.
- Wiersze bez oceny pokazują przygaszone «◎ —» z tooltipem wyjaśniającym, że porównanie z two-pagerem nie znalazło dopasowań (wcześniej: nic, co wyglądało jak błąd obok wierszy z oceną).
Dodano
- Przeprojektowanie chromu: karta launchera (wyrównany rząd kontrolek, dominujący przycisk podstawowy), pasek stanu terminalu z kropką stanu (bezczynny/uruchomiono/gotowe/błąd) respektujący reduced-motion, panel repostów z limitem wysokości i przyklejonym nagłówkiem (zbiór 1,560 klastrów renderował panel 155,000 px), oraz blok filtrów jako równomierna responsywna siatka z wyrównaną stopką.
Uwagi
- Reszta #/scan jest identyczna z v1.244.1 — zmieniło się tylko polerowanie chromu i cztery poprawki powyżej. Testy 5045 → 5068 unit.
[1.244.1] — 2026-10-08
Naprawiono
- Scan icons announce real values. The boost/fit/score icons’ accessible names leaked the raw dict templates (“Fit: {band}”, “Boosted by {by}”) —
{band}/{by}/{score}are now substituted (band word, booster keyword, numeric score). [HIGH a11y, caught live in the v1.244.0 regression round] - Title pipes split correctly. A 4-segment title like «C++ | Rust | Go Developer | Onsite» no longer lifts “Go Developer” out as a “country” — the split demands the segment resolves to a real country (conservative
Countries.detectCountry). - Meta dates render for every row.
daysSinceaccepted date-only ISO, but the API serves full timestamps for ~83% of dated rows — those rows showed no date segment.
Uwagi
- Reszta #/scan jest identyczna z v1.244.0 — zmieniły się tylko trzy poprawki powyżej.
- Świadomie nie zrobione: stan filtrów w hashu URL, nawigacja wierszy klawiaturą i parsowanie
5 lakhs INR(wcześniejsze zadania).
[1.244.0] — 2026-10-08
Wyniki skanu czytają się jak lista, a nie jak ściana: jedna oferta = dwa wiersze, sygnały to ikony, a skan 700 ofert to stronicowana tabela zamiast strony o wysokości 37,000 px.
Naprawiono
- Anatomia wiersza. Każda oferta renderuje się jako ograniczony dwuwierszowy wiersz: linia 1 to tytuł, linia 2 to
company · location · source · date · work-type. Odznaka promowania, pas dopasowania tytułu i wynik dopasowania stały się ikonami ze zlokalizowanymi nazwami dostępnymi i podpowiedziami (czytniki ekranu odczytują «Соответствие: сильное» / „Fit: strong”, a nie ścianę słów); odznaki zaufania i relokacji złożyły się do tej samej szyny. Seniority i wynagrodzenie pozostają kolumnami pomocniczymi widocznymi tylko na desktopie. - Higiena tytułów. Końcowy segment
| Germany | Remotejest wydzielany z tytułu do linii metadanych — z uwzględnieniem Unicode, tylko gdy ogon jest prawdziwym znacznikiem trybu pracy, a środkowy segment ma kształt miejsca (uzasadnione piony jak „C++ | Rust | Go Developer” nigdy się nie dzielą). - Koniec z rozlewaniem się w poziomie. Stały układ tabeli,
min-width: 0, tytuł i metadane skracane wielokropkiem do jednej linii z pełnym tekstem w podpowiedzi: zero przepełnienia strony i zero wewnętrznego przewijania tabeli przy 1440 px i 390 px (stara strona przepełniała się o 675 px przy szerokości telefonu). - Stronicowanie. Wyniki renderują się po 50 na stronę (do wyboru 25/50/100/200) — skan 700 ofert ma teraz ~4,600 px wysokości zamiast ~37,000 px, a DOM trzyma ~1,000 węzłów zamiast 5,500+.
Dodano
- Testy kontraktów układu: dwuwierszowy wiersz, dostępne nazwy ikon (en + ru), budżet węzłów stronicowania i straż liczby/kolejności dopasowania tytułu działają w zestawie przeglądarkowym — przeprojektowanie nie może po cichu się zregresować.
Uwagi
- Testy 5036 → 5045 unit (zestaw przeglądarkowy zyskał kontrakty układu), średnie pokrycie 98.14 % linii / 89.34 % gałęzi (podłoga 96/86).
- To, co znajduje skaner, wzory punktacji i
last-scan.jsonpozostają nietknięte — dopasowanie tytułu nadal jest tylko adnotacją. - Poza tym wydaniem: stan filtrów w hashu URL i nawigacja po wierszach klawiaturą (follow-up); parsowanie
5 lakhs INR(istniejące wcześniej).
[1.243.2] — 2026-10-08
Naprawiono
- Wersja wdrożeniowa wycięta jako v1.243.2. Tag git v1.243.1 został przepięty po publikacji, a
git fetch --tagsna serwerze poprawnie odmawia nadpisania istniejącego tagu — więc v1.243.1 nigdy nie było wdrożeniowe. Ten tag niesie identyczne drzewo (poprawkę window-listenera modala na bazie v1.243.0) plus to podniesienie wersji. Nic więcej się nie zmieniło; opublikowany tarball npm 1.243.1 już zawierał poprawkę.
Uwagi
- Kod aplikacji jest identyczny z v1.243.1 — nowa jest tylko tag wdrożeniowy (
git fetch --tagsna serwerze odrzucił przepiętą v1.243.1). - Świadomie nie zrobione: wymuszenie aktualizacji tagu po stronie serwera (opublikowanych tagów się nie przenosi).
[1.243.1] — 2026-10-08
Naprawiono
- Modal „Zapisz wynik” faktycznie zamyka się teraz przy nawigacji. Strażnik z v1.243.0 nasłuchiwał
hashchangenadocument, gdzie to zdarzenie nigdy nie odpala — poprawka dotarła martwa i modal nadal blokował następny widok (złapane na żywo w produkcji w rundzie regresji v1.243.1). Strażnik nasłuchuje nawindow; test też tam dispatchuje i został sprawdzony na czerwono wobec zepsutego kodu.
[1.243.0] — 2026-10-08
Warstwa przeglądarkowa chroni twoją pracę i mówi twoim językiem: żadnych utrat niezapisanych edycji, żadnych cichych awarii, żadnego cichego angielskiego w przetłumaczonym interfejsie, kontrast AA wszędzie.
Naprawiono
- Niezapisane edycje przetrwają ponowne renderowanie. Edytor CV przechowuje brudny bufor i przywraca go przy każdym renderze — „Anuluj”, zmiana języka lub przejście do CV Studio wywołują teraz pytanie zamiast odrzucać zmiany; plan kariery przechowuje swój wygenerowany tekst w ten sam sposób. Błędy ładowania w Config/CV Studio/career-plan/memory/two-pager pokazują komunikat o błędzie i wyłączają Zapis, zamiast po cichu nadpisywać plik pustkami.
- Modal „Zarejestruj wynik” nie przeżywa już nawigacji. Otwarcie go na
#/trackeri kliknięcie innego widoku pozostawiało go blokującego całą stronę (odkryte podczas dwustanowiskowej regresji z v1.242.1) — teraz zamyka się przy zmianie trasy; jego siostrzane widoki skanu zatrzymują przy nawigacji także swoje strumienie SSE i odczepiają nasłuchiwacze. - Parsowanie wynagrodzeń i słów kluczowych czyta każde pismo. Żetony słów kluczowych używają granic słów Unicode (cyrylica,
c++,.netfiltrują się poprawnie, zamiast zerować listę wyników); jeden wspólny parser wynagrodzeń naprawia$182.9K - $240K,от 100 000 руб,100 тыс. руб.,50 000 Kč(wcześniej 50 mln USD) oraz semantykę zakresów ($100-150K); wymagane „Niemcy lub Holandia” nie liczy się już jednocześnie jako spełnione i naruszone. - Strumienie domykają się dokładnie raz. Zerwane połączenie SSE dostarczało błąd dwukrotnie i mogło na zawsze zostawić wyłączony przycisk Generuj; każdy stan końcowy (done/error/close/throw, łącznie z zabitym procesem potomnym) domyka jedną ścieżkę i ponownie włącza przycisk. Auto-pipeline wypłukuje swój ostatni zbuforowany fragment zamiast go porzucać.
- Prywatność i poprawność na ubocznych ścieżkach. Treść zgłoszenia błędu nie zawiera już adresu URL ocenianej oferty ani slugów raportów; prywatność CV maskuje nagie linki
linkedin.com/in/…i nazwy PISANE WERSALIKAMI oraz przestaje psuć daty w formacie europejskim; określanie kraju wybiera najdłuższe dopasowanie i odmawia zgadywania, gdy wymienione są dwa kraje („Cambridge, MA” już nie → Wielka Brytania); pobierane pliki zachowują nazwy pisane cyrylicą. - Router i a11y. Skip link nie prowadzi już do 404 na
ontent; aktywny element nawigacji nosiaria-current="page"; jedno<main>/jedno<nav>; Escape zamyka mobilną szufladę (która jest teraz naprawdę poza kolejnością tabulacji, gdy jest zamknięta);scroll-padding-toputrzymuje fokus widoczny za przyklejonymi paskami; przyklejony baner nie zasłania już górnego paska. - Kontrast jest AA w obu motywach — ciemne toasty były białym na białym (1.10:1): toasty, przyciski, banery i linki na
--rauschkorzystają teraz z tokenów niezmiennych względem motywu, pilnowanych obliczanymi testami kontraktowymi WCAG (≥ 4.5:1). - Wszystko inne z tej rundy: evaluate wyświetla ostrzeżenie o ucięciu; memory/config/two-pager odmawiają Zapisu po nieudanym ładowaniu; scan przestaje zostawiać osierocone połączenia SSE; wyniki skanu klasyfikują boardy oparte o API na podstawie rejestru serwera, a nie rozjazdanego regexa; „Proceed with Caution” w trackerze to ostrzeżenie, a nie czerwona odznaka; statystyki agregują zlokalizowane statusy; wykresy słupkowe czytają się poprawnie w RTL; dokumentacyjny FAB nie zasłania już treści na telefonach;
GET /app.jsodpowiada 404 zamiast powłoki index;GET /api/runnerszwraca listę swoich akcji.
Dodano
- Duński dołącza do autowykrywania — przeglądarka
da-DKdostaje teraz duński interfejs (słownik był kompletny, wykrywanie go pomijało);zh-Hant*mapuje się na chiński tradycyjny.cv-diagnostics— lista kontrolna CV — jest w pełni zlokalizowana (28 kluczydiag.*× 17). Dodano 26 etykiet specyfikacji pól; usunięto 31 martwych kluczy; listy dostawców nie twierdzą już, że Hermes jest „ostatni w automatycznej kolejności”; aria-labely docs-fab/menu są zlokalizowane.
Uwagi
- Testy 4812 → 5036 jednostkowe, przeglądarkowe 118 + nowe kontrakty nawigacji/kontrastu, średnie pokrycie 98.15 % linii / 89.34 % gałęzi (minimum bramki 96/86).
- Poza tym wydaniem: przeprojektowanie
#/scan(Faza 4 — v1.244.0, spec napisana); dedykowany klucz słownikaexport.docxFailed(ta awaria korzysta zcommon.error);5 lakhs INRnadal parsuje się jako 5 (istniejące wcześniej zachowanie).
[1.242.1] — 2026-10-08
Naprawiono
- Archiwum wydania znowu nie zawiera symlinków
node_modules. Tag git v1.242.0 niósł symlinknode_modulesw katalogu głównym orazsite/node_modules(powszechnygit add -Aprzemył je obok wzorców ignore ze zakończonym ukośnikiem), przez co tar-rozpakowanie wdrożenia serwerowego padło — wdrożenie bezpiecznie się wycofało, a produkcja pozostała na 1.241.1. Oba symlinki zdjęto z trackingu i poszerzono wzorce ignore; tarball npm nigdy nie był dotknięty (npm wykluczanode_modulesprzy pakowaniu).
Uwagi
- Kod aplikacji jest identyczny z v1.242.0 — tylko pakowanie. Treść poprawek źródeł trafia na produkcję z tym wdrożeniem (v1.242.0 nigdy nie dotarło na produkcję: wdrożenie serwerowe wycofało się po błędzie tar).
- Świadomie nie zrobione: ponowne tagowanie v1.242.0 (npm opublikował już 1.242.0; tarball w rejestrze jest czysty — npm wyklucza
node_modulesprzy pakowaniu).
[1.242.0] — 2026-10-07
Warstwa danych skanera jest znowu godna zaufania: martwe źródła znów żyją, zniekształcona odpowiedź nie może już podszywać się pod pusty board, a wrogi adres URL boarda nie może już przekierować skanu.
Naprawiono
- Martwe źródła żyją ponownie. justjoin (koperta API zmieniła się na
{data, meta.next.cursor}) czyta pełny katalog przez przejście po kursorze z nowymi polami wynagrodzenia; nofluffjobs odpowiada 400 bezsalaryCurrency— wysyłane jest wymagane przez rodzica zapytanie, a wyniki są stronicowane (pageTo). himalayas i jobicy widziały tylko ~20 najnowszych ogłoszeń spośród 100k+ — oba przechodzą teraz przez pełne katalogi (stronicowanie offsetowe / kursorowe z limitami stron). - Odpowiedź 200 o złym kształcie rzuca błąd już na stronie 1. ~40 źródeł odczytywało zniekształcone odpowiedzi lub odpowiedzi typu challenge jako „0 ogłoszeń”, a skan „udawał się” po cichu. Nowe strażniki
server/lib/sources/_shape.mjs(requireArray/requireContainer/requireObject) czynią tę awarię głośną w każdej rodzinie; awaria na późniejszej stronie zachowuje już zebrane strony; stronicowanie zatrzymuje się na surowej długości strony, a nie na liczbie po odfiltrowaniu. - SSRF: sprawdzanie dostawców po podciągu zastąpiono sparsowanymi pinami dokładnego hosta. lever (
clever.comzawieralever.co), greenhouse (5 hostów + starsze hosty path-slugboards[.eu].greenhouse.io), ashby, smartrecruiters, workable, gem REST, ibm, arbeitsagentur, hecklerkoch (tylko www), workingnomads (http://169.254.169.254było osiągalne za strażnikiem DNS), remoteok, remotive, rss, successfactors. Wszędzieredirect:'error'; adresy URL ogłoszeń muszą byćhttps:na przypiętym hoście (javascript:/data:/ spoza hosta są odrzucane). - Jeden źle skonfigurowany wpis w portals nie przerywa już całego skanu.
resolveAdapterprzechwytuje rzucane przez adaptery wyjątki,detectApijest opakowany per firma, a adaptery rzucające zwracająnull; błędy pobierania comeet redagują?token=zanim trafią do logów lub rekordów kwarantanny. - Stronicowanie i świeżość. workday przechodzi przez tenantów ponad pierwsze 100 ogłoszeń (strony offsetowe,
MAX_PAGES); telegram zachowuje NAJNOWSZE wpisy i stronicuje przez?before=, zamiast po cichu zostawiać najstarsze; tencent idzie dalej, gdy brakujeCount; taleo parsuje francuskie tabele nagłówkowe; avature zatrzymuje się na surowej długości strony; znaczniki daty w UTC (amazon z błędem o jeden dzień na wschód od UTC, torre, workingnomads, trudvsem); zdekodowane encje HTML (geekjob, getmatch, hh); mycareersfuture zwraca pełny 12-polowy kształt ogłoszenia. - Zaostrzone wykrywanie pracy zdalnej. arbeitsagentur, vdab, rippling, teamtailor: procent wymiaru etatu („Verpleegkundige (100%)”,
bundesweit) i słowo „distributed” („Distributed Systems Engineer”) nie oznaczają już ogłoszeń stacjonarnych jako Remote.
Dodano
tests/adapters-pin-coverage.test.mjsuzupełnia pokrycie gałęzi pinów hostów, wprowadzone wraz z tymi pinami.
Uwagi
- Testy 4419 → 4812, przeglądarkowe 118. Średnie pokrycie 98.15 % linii / 89.36 % gałęzi (minimum bramki 96 / 86).
- Poza tym wydaniem: ustalenia po stronie klienta z tej samej rundy przeglądu (Faza 3 — widoki, biblioteki, CSS/a11y, i18n);
sources/habr.mjsnadal nie ma dedykowanego pliku testowego (wyjątek od rosnącego poziomu bazowego).
[1.241.1] — 2026-10-07
Oceny na żywo działają od początku do końca w każdej wersji językowej, mapa ofert umieszcza długie oferty z wieloma lokalizacjami, a wdrożenie nie przerywa już trwającego skanu.
Naprawiono
- Oceny widzą całą metodę. Budżet kontekstu (144 KB) nadal ucinał koniec
modes/oferta.mdpo wstawieniu CV i profilu, więc każda ocena na żywo pomijała swoje ostatnie bloki. Budżet wynosi teraz 192 KB, a miękki limit promptu 256 KB, zdefiniowane w jednym miejscu wllm-dispatch.mjs. - Raporty w wybranym języku. Instrukcja językowa teraz otwiera prompt, a nie tylko go zamyka, a zwykłe słowa (rola, zespół, design…) są pisane w języku raportu; po angielsku zostają tylko nazwy, technologie i dosłowne cytaty. Naprawia raporty po hindi i japońsku, które były w większości po angielsku.
- Wolne oceny nie kończą się już błędem HTTP 502. Limit czasu oceny wynosi 300 s (wcześniej domyślne 180 s dostawcy).
- Litery bloków w hindi. Raport, który zapisuje litery A–G w dewanagari (
## ए),## बी)…## जी)), jest rozpoznawany, aSCORE:akceptuje lokalne cyfry (३.८,٣٫٨,3.8) i przecinek dziesiętny. - Mapa ofert: długie lokalizacje. Komórka w rodzaju „Berlin Office · Berlin · Germany · Bosnia · …” (ponad 300 znaków) była odrzucana z HTTP 400, a oferta nie miała znacznika. Teraz używane jest pierwsze prawdziwe miejsce (
·,;,|,/, podziały wierszy; segmenty „Remote …”, „(HQ)” i „Office” są pomijane); odrzucane jest tylko zapytanie dłuższe niż 2000 znaków. - Wdrożenie a cogodzinny skan. Wdrożenie wstrzymuje timery skanu i automatycznej oceny, czeka na zakończenie trwającego (do 15 min), restartuje i zawsze wznawia timery — również przy wycofaniu.
Dodano
- Mapa ofert na cvstart.org we wszystkich 17 językach oraz w angielskim i rosyjskim README.
- Zrzuty mapy we wszystkich językach — po jednym na język (
scripts/capture-map-screenshots.mjs), we wszystkich 17 plikach README, na cvstart.org i w nowym podrozdziale pomocy „Jak korzystać z mapy” (§33, ×17).
Uwagi
- Testy 4404 → 4419, przeglądarkowe 118. Zdalne QA (wszystkie trasy, strona, linki i LLM na żywo × 17 wersji językowych) zielone na produkcji.
- Poza tym wydaniem: ocenianie w trybie strumieniowym — limit 300 s pozostaje sztywny (wolny model lokalny wciąż może go osiągnąć), a most Hermes nadal działa bez strumieniowania.
[1.241.0] — 2026-10-07
Wydanie wzmacniające po przeglądzie kodu przez 28 agentów (~190 zweryfikowanych ustaleń): zamknięto klasy problemów dotyczące bezpieczeństwa, awarii procesu i utraty danych, a do tego mapa ofert pracy wniesiona przez @bullitt186.
Dodano
- Mapa ofert (
#/map) — oferty z pipeline, ostatniego skanu i trackera na mapie OpenStreetMap, geokodowane przez Nominatim z identyfikującym nagłówkiem User-Agent, kolejką 1 żądanie/s, wycofywaniem się przy błędach i pamięcią podręczną na dysku. Leaflet jest serwowany z tego serwera (bez CDN); CSP zyskuje wyłącznie źródło kafelków wimg-src. Wniósł @bullitt186 (#381). - Strażnik żądań — serwer odrzuca
Host, którego nie obsługuje (DNS rebinding), oraz zapisy z innych witryn i żądania GET z efektami ubocznymi (/api/stream/*,/api/run/*,/api/geocode). Odwrotny proxy przekazujący publiczną nazwę wpisuje ją doALLOWED_HOSTS; workflow wdrożeniowy zapisuje ten drop-in systemd na podstawie publicznego adresu URL. - Bramka pokrycia —
npm run test:coverage:gate(scripts/coverage-report.mjs) wypisuje pokrycie linii/gałęzi dla każdego pliku i kończy się błędem poniżej rosnącego poziomu bazowego.
Naprawiono
- Zniekształcone żądanie nie zatrzymuje już serwera. Express 4 ignorował odrzucone asynchroniczne handlery, więc pole błędnego typu w
/api/deep,/api/auto-pipeline,/api/career-plan,/api/trackerlub bajt NUL w/api/statskończyły proces; teraz są to odpowiedzi JSON 400, a każde inne odrzucenie staje się 500. - Przerwany lub nieudany skan nie kasuje już ostatnich wyników.
last-scan.jsonjest zachowywany, gdy skan zatrzymano lub wszystkie źródła zawiodły, a skan pojedynczej firmy scala wyniki zamiast je zastępować. Jeden źle skonfigurowany wpis wportals.ymlnie przerywa już całego skanu. - Oceny widzą całą metodę. Pliki trybów były ucinane na 16 KB, więc
oferta.md(92 KB) tracił bloki C–G; limity na plik wynoszą teraz 128 KB dla trybów i 64 KB dla CV, a ucięcie jest zgłaszane. Puste lub ucięte odpowiedzi kończą się błędem zamiast zapisu pustego raportu. - SSRF: kolejne przekierowania są ponownie sprawdzane pod kątem prywatnych celów, sprawdzana jest każda odpowiedź DNS, termin skanu obejmuje treść odpowiedzi, klucze
*_BASE_URLtrafiają tylko do hosta dostawcy (Hermes/Ollama: loopback lub LAN), pandoc działa z--sandbox. - Zawieszenia pętli zdarzeń: dwa kwadratowe wyrażenia regularne (usuwanie HTML, sanityzacja markdown) zastąpiono liniowymi skanerami.
- Utrata danych: usunięcie wiersza pipeline zachowywało wynagrodzenie innych wierszy;
$&w adresie URL psułopipeline.md; zapisy mock-interview, networkingu i deep-research nadpisywały wcześniejsze pliki; historia rozmowy kwalifikacyjnej zachowywała pierwsze 40 tur zamiast ostatnich. - Warstwa LLM: auto-pipeline i deep research respektują
LLM_PROVIDERi każdego dostawcę przez wspólny dispatch, rejestrują zużycie i zgłaszają ucięcie; Gemini evaluate/test nie zapisuje już raportu; OpenAI używamax_completion_tokens, aOPENAI_MODELtylko dla Codex jest wysyłany jakogpt-5; opis stanowiska jest ujęty jako niezaufane dane. - Raporty, deep i PDF inline przekazują
--skip-fact-check(weryfikacja faktów CV blokowała każdy raport z liczbami); format strony z profilu nie jest już nadpisywany. - Skanery: kwarantanna jest kluczowana adresem URL (naprawa adresu pozwala go ponowić), deduplikacja w obrębie przebiegu po kanonicznym adresie URL, puste wpisy list nie dopasowują już wszystkiego, zapisy atomowe, wiersze historii
skipped_*nie są „widziane”. - Kontrola procesów: eskalacja SIGKILL nigdy się nie uruchamiała; przebiegi wsadowe zabijają całą grupę procesów po rozłączeniu.
- CI i wydanie: CI uruchamia teraz bramki zgodności changelogu, workflow i i18n; uprawnienia workflow o najmniejszych przywilejach; sekrety produkcyjne tylko w środowisku
production; pakiet npm zawiera terazdocs/help/. - Testy: żaden test nie dotyka już sieci ani prawdziwego projektu nadrzędnego (jawny
CAREER_OPS_ROOTjest zawsze respektowany); skopiowane algorytmy zastąpiono kodem produkcyjnym.
Uwagi
- Testy 4056 → 4404, przeglądarkowe 118. Poziom bazowy pokrycia serwera: linie 96,7 %, gałęzie 86,3 % (
scripts/coverage-baseline.json). - Specyfikacje mieszczą się teraz w jednym folderze,
docs/sdd/specs/; plan programu todocs/sdd/PLAN.md, a macierz niezmiennik→bramka todocs/sdd/TRACEABILITY.md. - Uwaga dla operatora: za odwrotnym proxy ustaw
ALLOWED_HOSTS=<publiczny host>; bazowy adres URL Ollama/Hermes na hoście publicznym jest teraz odrzucany.
[1.240.0] — 2026-10-06
Parytet z projektem nadrzędnym — career-ops main @ 62905981 (VERSION 1.35.0, 177 commitów upstream od b39931e). Sześć nowych źródeł — 103 → 109 (104 EN + 5 RU) — poprawki przeniesione do ośmiu istniejących dostawców oraz format pipeline w postaci listy kontrolnej, wniesiony przez @bullitt186.
Dodano
- Sześć nowych źródeł — 103 → 109 (104 EN + 5 RU), adaptery EN 98 → 104.
- ADP Workforce Now (
workforcenow.adp.comzcid+ccId) — paginacja$skipwedług faktycznie zwróconej liczby wierszy; odpowiedź bezjobRequisitionsi bezmetazgłasza błąd zamiast być odczytana jako pusta tablica; opcjonalne uzupełnianie szczegółów (adpWorkforcenow.fetchDetails, domyślnie 25, limit 100). - Gupy (
employability-portal.gupy.io) — przeszukiwanie całej tablicy po słowach kluczowych, od najnowszych, z wczesnym zatrzymaniem przysince_days;workplaceTypejest odczytywane jako pojedynczy ciąg pt-BR, więc oferty hybrydowe nie giną; poufne strony kariery są odrzucane. - JazzHR (
*.applytojob.com) — parser kart z awaryjnym wariantem samej kotwicy, dzięki czemu częściowy redesign nadal daje oferty; linki do ofert przy zerze sparsowanych kart zgłaszają błąd, a naprawdę pusta tablica zwraca[]. - Startup Jobs (
startup.jobs/feeds/jobs) — RSS, jedno żądanie; zniekształcona, HTML-owa lub ucięta odpowiedź zgłasza błąd zamiast zwracać[](poprawka z przeglądu po scaleniu w projekcie nadrzędnym,08fe5d06); CDATA i komentarze są maskowane przed dopasowaniem elementówitem. - Taleo (
<tenant>.taleo.net,tre.taleo.netodrzucany) — GET powłoki, potem POSTsearchjobs; powłoka bez identyfikatora portalu zgłasza błąd jako prywatna tablica; kolumny są dopasowywane po nagłówku. - UKG Pro / UltiPro (
recruiting[N].ultipro.{com,ca}) —Top=50+Skip,totalCountnigdy nie jest warunkiem zatrzymania, limit stron 100 (ograniczany do 1500), opcjonalne strony szczegółów parsowane przejściem po nawiasach klamrowych uwzględniającym ciągi znaków.
- ADP Workforce Now (
Naprawiono
- Pipeline w formacie listy kontrolnej projektu nadrzędnego — upstream career-ops zapisuje
data/pipeline.mdjako sekcje## Pending/## Processedz wierszami- [ ] url | …, które UI odczytywało jako 0 oczekujących, a zapisywało, dopisując blok kodu na końcu pliku, gdzie projekt nadrzędny nigdy nie zagląda.parsePipeline,addPipelineUrliremovePipelineUrlodczytują i zapisują teraz ten kształt (deduplikacja także względem przetworzonych wierszy; wynagrodzenie jako oznaczony segmentnote: comp …); format z blokiem kodu bez zmian. Wniósł @bullitt186 (#380). - Kraj dołączany do lokalizacji — Ashby (główny
address.postalAddress), Breezy (country.name) i Recruitee (płaskielocation) dopisują kraj, chyba że nazwa już zawiera go jako całe słowo, więc zdalna oferta z głównym adresem w UK i dodatkowym w USA nie jest już odrzucana przez filtr lokalizacji. - MokaHR — host regionalny
hire-r1.mokahr.comjest akceptowany (biała lista to dokładnieapp.mokahr.com+hire-r1.mokahr.com), POST do API i linki do ofert używają własnego hosta tablicy, a zwrócone w treścisuccess:falsezgłasza teraz błąd zamiast być odczytane jako pusta tablica. - Avature — karty
article--jobssą parsowane (tytuł z kotwicy w nagłówku, lokalizacja z elementu spanicon-address). - SAP SuccessFactors — adres zapisanego wyszukiwania
/go/<Category>/<id>[/<offset>]/rozwiązuje się teraz do katalogu głównego najemcy; wcześniej trafiał na…/tile-search-results/, które odpowiada 200 z zerem kafelków. - Deutsche Bahn — db.jobs wyświetla pustą stronę wyników, gdy zawiera ona ofertę, której nie potrafi wyrenderować; przeszukiwanie sortuje teraz według
pubExternalDate_tdtpo 1000 na stronę (maks. 5 stron), zatrzymuje się według surowej liczby kotwic trafień i zgłasza błąd przy braku nagłówka wyników lub niesparsowanych linkach do ofert, zamiast zwracać okrojoną tablicę. - HigherEdJobs — strona wyzwania Incapsula zwrócona z HTTP 200 była parsowana jako zero elementów i odczytywana jako pusta tablica; teraz zgłasza błąd.
- Test czytał prawdziwy projekt nadrzędny na maszynie programisty —
tests/reports-list-cache.test.mjsustawiałCAREER_OPS_ROOTna katalog tymczasowy bezcv.md/portals.yml, którypaths.mjsignoruje, więc lokalnie liczył raporty projektu nadrzędnego (6 zamiast 3), a CI, bez projektu nadrzędnego obok, przechodziło.
Uwagi
- Testy 3782 → 4056. Nowe zestawy:
sources-adp-workforcenow,sources-gupy,sources-jazzhr,sources-startup-jobs,sources-taleo,sources-ultipro,sources-location-country-fold,sources-deutschebahn-blanked-page,sources-higheredjobs-challenge-page, a takżeparsers-pipeline-checklistz #380. - Projekt nadrzędny: fork doprowadzono do poziomu upstream
main(144 → 0 commitów zaległości), a cztery rozbieżności z ADR-0002 potwierdzono jako nienaruszone; cofnięcie przez upstream cyrylickiegoLOCATIONISH_REnie zostało przeniesione. - Już wydane w v1.239.0, nie powtarzane: AppliTrack, NEOGOV, Red Rover, SchoolSpring, OCC Mundial, osadzone tablice Greenhouse, Workday
myworkdaysite.com.
[1.239.4] — 2026-09-29
Poprawka po regresji na żywo wersji v1.239.3.
Naprawiono
- Oceny po koreańsku i po chińsku tradycyjnym zgłaszały brak podsumowania oceny. Te raporty mają 10–11 tysięcy znaków, a podsumowanie jest na końcu, więc wypadało poza limit 8192 tokenów wyjściowych. Oceny (i automatyczny pipeline) pozwalają teraz na 16384 tokeny, a gdy dostawca mimo to utnie odpowiedź, pierwsze ostrzeżenie mówi o tym zamiast wyliczać brakujące bloki.
- Test na żywo uznał krótką niemiecką odpowiedź za nieniemiecką (3 niemieckie słowa funkcyjne, żadnego angielskiego). Odpowiedź w formie listy może ich mieć mało; bez żadnych angielskich wystarczą teraz trzy.
- Testy 3778 → 3782.
Uwagi
- Trasy pogłębionego researchu i trybów zachowują limit 8192 tokenów: ich odpowiedzi w przebiegach na żywo nie osiągają go.
[1.239.3] — 2026-09-29
Poprawka po regresji na żywo wersji v1.239.2.
Naprawiono
- Oceny po arabsku nadal nie przechodziły kontroli A–G po tym, jak v1.239.2 naprawiła japoński i hindi. Zamaskowany szkielet nagłówków (bez tekstu raportu w logu) pokazał przyczynę: raport arabski zapisuje literę bloku po arabsku, w kolejności abdżad, niezależnie od promptu. Kontrola akceptuje teraz أ ب ج د هـ و ز jako A–G, gdy litera stoi osobno na początku nagłówka, tak jak już akceptowała cyrylickie sobowtóry; te same litery wewnątrz arabskiego słowa się nie liczą.
- Test na żywo wypisuje ten zamaskowany szkielet, gdy kontrola A–G zawodzi, aby następny przypadek dało się zdiagnozować z logu.
- Testy 3776 → 3778.
Uwagi
- Notatka do v1.239.2 mówiła, że kontrola nie zostanie złagodzona; dla arabskiego została, bo trzy przebiegi na żywo pokazały, że sam prompt nie utrzymuje łacińskiej litery.
[1.239.2] — 2026-09-29
Poprawka po regresji na żywo wersji v1.239.1.
Naprawiono
- Ocena po arabsku przetłumaczyła litery bloków, a po japońsku pominęła podsumowanie oceny. Wersja v1.239.1 powtarzała w ostatnim wierszu promptu tylko język. Teraz ten wiersz mówi też, że łacińska litera A–G w każdym nagłówku i blok
---SCORE_SUMMARY---(znaczniki i klucze po angielsku) nie są tłumaczone, oraz prosi o własne pismo języka. - Testy 3775 → 3776.
Uwagi
- Kontrola raportu nie została złagodzona, by przyjmować przetłumaczone litery lub znaczniki: stabilność formatu zapewnia prompt.
[1.239.1] — 2026-09-29
Poprawka po regresji na żywo wersji v1.239.0.
Naprawiono
- Oceny po japońsku i ukraińsku wracały prawie w całości po angielsku. Polecenie języka stało na początku promptu, przed dziesiątkami kilobajtów angielskich plików projektu i ogłoszenia. Teraz prompt powtarza język w ostatnim wierszu.
- Test na żywo zgłaszał nieudane skanowanie, gdy serwer już wykonywał inne (skanowanie cogodzinne, ponowione tuż po wdrożeniu). Odmowa drugiego skanowania przez serwer jest poprawna; test teraz czeka i ponawia próbę, do 30 minut.
- Testy 3774 → 3775.
Uwagi
- Ograniczenie serwera do jednego skanowania naraz nie zostało złagodzone: drugie skanowanie nadal jest odrzucane z
SCAN_BUSY. Zmienił się tylko test.
[1.239.0] — 2026-09-29
Parytet z career-ops @ b39931e: pięć nowych źródeł i trzy przeniesione poprawki.
Dodano
- Pięć nowych źródeł (98 → 103; adaptery anglojęzyczne 93 → 98): AppliTrack (
applitrack.com/<okręg>), NEOGOV (SchoolJobs / GovernmentJobs), Red Rover (jobs.redroverk12.com/org/<id>) i SchoolSpring (<okręg>.schoolspring.com) dla rekrutacji w szkołach i sektorze publicznym oraz OCC Mundial, największy serwis z ofertami pracy w Meksyku (jawneprovider: occz zapytaniami wyszukiwania). Każde jest przypięte do swojego hosta, działa tylko przez HTTPS i odrzuca przekierowania. - Testy 3500 → 3774.
Naprawiono
- Osadzone tablice Greenhouse (
job-boards.greenhouse.io/embed/job_board?for=<tablica>) wskazywały tablicę o nazwie „embed” i kończyły się błędem; teraz tablica pochodzi z?for=, i tylko na prawdziwym hoście Greenhouse. - Tablice Workday na
myworkdaysite.com(/recruiting/<tenant>/<site>) nie były rozpoznawane; teraz są skanowane, a linki do ofert prowadzą na ten sam host. - Nazwa raportu z nawiasami (
042-acme-(berlin)-….md) była w trackerze ucinana na pierwszym); teraz cała nazwa zostaje zachowana.
Uwagi
- Zmiany projektu nadrzędnego dotyczące tylko CLI nie są przenoszone — szablony PDF i CV, scaffolder, uruchamianie wsadowe, import career-profile, pokrycie słów kluczowych ATS, tłumaczenia trybów rozmowy, host CLI
pi: web-ui ich nie uruchamia. - Otwarcie takiego raportu z trackera nadal wymaga, by trasa raportów akceptowała nawiasy w nazwie pliku; ta trasa nie zmienia się w tym wydaniu.
[1.238.3] — 2026-09-27
Strony odpowiadają także podczas skanu, a logi zdalnego QA nie ujawniają już hosta produkcyjnego.
Naprawiono
- Pulpit i raporty ładowały się sekundami, a podczas skanu kończyły się timeoutem.
/api/reportsi/api/dashboardprzy każdym żądaniu czytały i parsowały wszystkie raporty — około 3,7 s na serwerze produkcyjnym, blokując każde inne żądanie; w trakcie skanu ładowanie stron trafiało na 30-sekundowy timeout. Sparsowane nagłówki są teraz przechowywane w pamięci podręcznej dla każdego pliku i odświeżane przy jego zmianie, więc lista kosztuje jedno sprawdzenie pliku na raport (500 raportów: lokalnie 430 ms → 3 ms). - Wynik zdalnego QA mógł wypisać część hosta produkcyjnego do publicznego logu. GitHub maskuje sekret tylko wtedy, gdy pojawia się w całości, a komunikat przycięty do 180 znaków kończył się w połowie nazwy hosta. Wyniki i całe raporty są teraz cenzurowane przed przycięciem.
- Każda ocena AI była oznaczana jako błędna. Prompt nigdy nie prosił o blok
---SCORE_SUMMARY---, którego wymaga kontrola raportu (skrypty oceny projektu nadrzędnego o niego proszą), a przetłumaczony raport tłumaczył też słowo “Block”, więc kontrola nie znajdowała sekcji. Teraz prompt prosi o podsumowanie i literę bloku w każdym nagłówku, kontrola akceptuje przetłumaczone słowo przed literą, a blok podsumowania jest usuwany, zanim raport trafi na stronę lub zostanie zapisany.
Dodano
- Testy 3488 → 3500.
Uwagi
- Skaner nadal działa wewnątrz procesu serwera; to wydanie usuwa drugą dużą blokadę, ale nie przenosi skanu do workera.
[1.238.2] — 2026-09-27
Poprawka błędów 502, które serwer produkcyjny wciąż zwracał podczas cogodzinnego skanu.
Naprawiono
- Strony i zasoby zwracały 502 podczas skanu. Node zamyka bezczynne połączenie keep-alive po 5 s, a Caddy używa bezczynnych połączeń ponownie do 2 minut. Gdy skan w procesie zajmował serwer, Node zamykał gniazda, na które Caddy właśnie wysłał żądanie, i Caddy odpowiadał 502 connection reset by peer (62 razy podczas jednego skanu, przy zdrowym serwerze). Teraz serwer trzyma bezczynne połączenia 125 s — dłużej niż proxy — więc zawsze pierwsze zamyka proxy.
Dodano
deploy.yml→verifypokazuje, dlaczego proxy odpowiedziało 502 (rodzaje błędów, adresy zamaskowane), liczbę 502 na minutę od ostatniego restartu i wynik cogodzinnego skanu.release.ymlpotrafi utworzyć brakujący tag przy ręcznym uruchomieniu, więc wydanie da się opublikować tam, gdzie nie można wypchnąć tagów.- Testy 3486 → 3488.
Uwagi
- Skan nadal działa wewnątrz procesu serwera i może go zajmować przez kilka sekund; przeniesienie go do workera nie jest częścią tej poprawki.
[1.238.1] — 2026-09-27
Poprawka stabilności po pierwszej regresji na żywo serwera produkcyjnego: jeden skan naraz i poprawki strony.
Naprawiono
- Dwa skany naraz wywracały serwer. Każde
GET /api/stream/scanuruchamiało pełny skaner w procesie serwera bez żadnej ochrony; skan z UI nałożył się na cogodzinny timer i proces padł z JavaScript heap out of memory (dwa razy, w międzyczasie błędy 502). Teraz jeden skan naraz: drugie żądanie dostaje SSEerrorz kodemSCAN_BUSYi nic nie startuje. Workflow wdrożenia podnosi też limit pamięci serwera (heap_mb, domyślnie 448 MB). /helpi/changelogna cvstart.org przewijały się w bok na telefonie (a/changelogja/zh także na desktopie): długi kod i spis treści teraz się zawijają.- Brakowało hindi w alternatywach językowych sitemapy; kontrola i18n strony porównuje teraz sitemapę z rejestrem języków.
- Pomoc §19 kazała dodać klucz do „wszystkich 8” plików językowych — jest ich 17.
Dodano
- Zdalna regresja (
.github/workflows/remote-qa.yml): każda trasa × każdy język wdrożonej aplikacji (tylko odczyt), każda strona × język × telefon/desktop na cvstart.org, każdy link w README i wiki oraz, na żądanie, prawdziwy skan i wywołania AI na żywo w każdym języku. - Workflow wdrożenia serwera (
.github/workflows/deploy.yml):recon,deploy(z dokładnym wycofaniem) iverify(test dymny i raport stabilności). - Testy 3481 → 3486.
Uwagi
- Zużycie pamięci przez sam skaner nie zostało w tym wydaniu zmniejszone: ochrona nie pozwala na dwa skany naraz, a drop-in podnosi sufit. Profilowanie prawdziwego skanu 98 źródeł wymaga sieci produkcyjnej.
- Cogodzinny timer
career-ops-scannie został zmieniony;reconpokazuje teraz, jakie polecenia uruchamia.
[1.238.0] — 2026-09-27
Parytet z rodzicem — career-ops main @ 993085ce (VERSION 1.34.0, 182 commity od de2224a9). Cztery nowe źródła, dziesięć zwierciadlanych poprawek dostawców, zamknięta luka SSRF w całym skanerze i darmowa podpowiedź dopasowania tytułu w wynikach skanu.
Dodano
- Cztery nowe źródła — 94 → 98 (93 EN + 5 RU), 89 → 93 adapterów EN.
- Eploy (
provider: eploy) — czyta mapę witryny/live-jobs.xmlnajemcy na dowolnym markowym hoście (tylko HTTPS; literały IP,localhost,*.local,*.internali hosty jednoczłonowe są odrzucane). Odpowiedź niebędąca mapą witryny (strona logowania) rzuca wyjątek zamiast przechodzić jako zero ofert. Strony szczegółów są opt-in (eploy: { fetchDetails, detailLimit }). - HiringRoom (
*.hiringroom.com) — najpierw JSON-LD/portal/jobs, jako fallback stare karty/jobs; adresy URL oferthttp://w payloadzie są przebudowywane na HTTPS. - PeopleSoft Candidate Gateway — wykrywany po ścieżce
/psc/{site}/EMPLOYEE/HRMS/c/HRS_HRAM_FL.HRS_CG_SEARCH_FL.GBLna dowolnym markowym hoście. Sam podąża za przekierowaniami sesji PeopleSoft w obrębie tego samego originu (maks. 10 przeskoków, każdy przeskok ponownie przypinany do originu najemcy i sprawdzany pod kątem adresów prywatnych), odtwarza formularz „load more” i oznacza częściowy przebieg (peoplesoftIncomplete) zamiast raportować go jako kompletny. - PrevueAPS (
*.prevueaps.ca) — ustala identyfikator witryny ze strony z ofertami, a następnie czyta API JSON.
- Eploy (
- Podpowiedź dopasowania tytułu w wierszach
#/scan. Każdy wynik niesie przybliżony chip strong / related / weak fit, porównujący tytuł oferty z rolami docelowymi wconfig/profile.yml(target_roles.primary+ nazwy archetypów). To darmowe oszacowanie słów kluczowych: nigdy nie filtruje, nie zmienia kolejności ani liczby wyników, a dymek z podpowiedzią o tym mówi. Obliczane przy serwowaniu wyników, więc edycja profilu widoczna jest dopiero przy następnym odświeżeniu. Przetłumaczone ×17. Odzwierciedla parent #3261.
Naprawiono
- Bezpieczeństwo — zabezpieczenie przed DNS rebinding nigdy nie działało podczas prawdziwego skanu.
http-json.mjssprawdzał rozwiązane adresy tylko wtedy, gdy otrzymywał gołe globalnefetch, ale oba skanery wstrzykująmakeTimeoutFetch(), więc każdy skan pomijał tę kontrolę. Źródło wskazujące na nazwę hosta rozwiązującą się do10.xlub127.0.0.1było pobierane. Zabezpieczenie działa teraz wewnątrz samegomakeTimeoutFetch, w wyścigu z limitem czasu skanu, więc zawieszony resolver nie może zawiesić skanu. Znalezione podczas review tego wydania. - Bezpieczeństwo — adresy IPv6 osadzające adres IPv4 nie były traktowane jako prywatne.
http://[::ffff:127.0.0.1]/(który parser URL przepisuje na[::ffff:7f00:1]) przechodziłisValidJobUrl. Zarówno kropkowana, jak i szesnastkowa forma::ffff:a.b.c.d/::a.b.c.dsą teraz klasyfikowane po osadzonym adresie. Parent_ip-guard.mjs. - Rippling przeniesiono na API tablicy v2 (
ats.rippling.com/api/v2/board/<slug>/jobs), z paginacją (domyślnie 10 stron, maks. 50), blokadą hosta na linkach ofert i walidacją sluga. Wklejony URL API daje teraz prawdziwy slug zamiastapi. - Recruitee — oferty z wieloma lokalizacjami wymieniają każde miejsce (
A · B), demo-ogłoszenia(Sample)i wiersze bez tytułu są odrzucane, a oferta jest zachowywana, gdy przynajmniej jeden z jej dwóch adresów URL jest prawidłowy. - Pinpoint — zasiane demo-ogłoszenia (podwojone demo wideo) są odrzucane.
- Kanały Telegram — pierwsza linia z kilkoma
|nie jest już odczytywana jakoTytuł | Firma, a rozpoznawanych jest więcej słów opisujących rolę. Świadomy cyrylicyLOCATIONISH_REforka pozostaje nietknięty (ADR-0002). - Workday — 422/401/403 na pierwszej stronie jest sprawdzane jednorazowo; strona konserwacyjna Workday lub przekierowanie awaryjne oznacza tablicę jako martwą (kwarantanna w trybie strict). Żądania CXS i szczegółów odmawiają teraz przekierowań.
- BambooHR — przekierowane
/careers/listjest triażowane przez publiczny feed embed: puste oznacza żywą tablicę bez ofert, cokolwiek innego — martwą tablicę. - Heckler & Koch / Rheinmetall — goły
heckler-koch.com/rheinmetall.comjest przepisywany nawww., aby transport bez przekierowań mimo to go osiągnął. Ashby odmawia przekierowań. beesite tempuje strony przy użyciu odwoływalnegodelay(). - Filtry tytułów składają akcenty po obu stronach (skanery EN i RU), więc
Développeurjest wyłapywany przez negatywdeveloppeur. - Dopasowywanie firm w cooldownie rozumie nazwy niełacińskie i formy prawne firm (znaczniki CJK/koreańskie, tureckie kropkowane İ). Nazwy CJK dawniej zapadały się do pustego klucza i nigdy nie pasowały.
location_filter.strict: truezawodzi w sposób zamknięty przy pustej lokalizacji, gdy ustawiona jest lista dozwolonych lub zablokowanych.- Liveness — nowe kontrole publicznego API dla osadzeń Greenhouse (
gh_jid), Arbeitsagentur i We Work Remotely; SmartRecruiters decyduje teraz na podstawie flagiactiveoferty. - PeopleSoft — względna akcja formularza „load more” jest teraz rozwiązywana względem strony wyszukiwania, a nie korzenia originu.
Uwagi
- Testy 3210 → 3481. Nowe zestawy:
sources-eploy,sources-hiringroom,sources-peoplesoft,sources-prevueaps,title-fit,fetch-timeout-dns-guard,cooldown-company-match-unicode,liveness-api-more-rungs,ru-scanner-title-accent-fold. - Nie przeniesiono, z uzasadnieniem: brzegi słów Unicode w filtrze lokalizacji (filtr web-ui jest oparty na podciągu, więc nie ma brzegu do naprawienia — celowy pełny port filtra lokalizacji z parenta to praca na przyszłość); deduplikacja requizycji o tym samym tytule (web-ui deduplikuje tylko po URL); ostrzeżenia o repostach agregatorów, zakres domen blacklisty, potwierdzenia niezweryfikowanego zera i migracja
scan-runs.tsv(web-ui nie ma żadnej z tych powierzchni); podział na fasety i tagi obcięcia w Workday (web-ui pobiera jedną stronę na tablicę);enrichDatew BambooHR (brak hooka wzbogacania daty); refaktoryzacja sleep w_http.mjsparenta w ~20 dostawcach (web-ui już używa współdzielonego, odwoływalnegodelay); updater, doctor, PDF, tracker/merge-tracker,validate-profile,discover-new-companies, aplikacja Next.jsweb/, boty GitHub — tylko CLI lub przekazywane dalej. - Świadomie utrzymane inaczej niż u parenta: Heckler & Koch / Rheinmetall pozostają tylko HTTPS (bez uaktualnienia
http→https); martwa tablica Workday w normalnym skanie nadal zwraca[], zamiast powodować niepowodzenie skanu.
[1.237.1] — 2026-09-22
Poprawka po zewnętrznym przebiegu QA dla v1.237.0. Poprawkę Jobstreet potwierdzono z zewnątrz po raz pierwszy: na hostach AU, NZ, HK i MY stara forma /id/job/<id> zwraca czyste 404, a nowa /job/<id> trafia na prawdziwą trasę chronioną przez Cloudflare; na id.jobstreet.com zachodzi sytuacja odwrotna. Utracone linki były prawdziwe. Znaleziono dwie wady, obie w tym, co samo v1.237.0 dodało.
Naprawiono
- Etykieta linku do książki była zlokalizowana, ale jej cel — nie. Wszystkie 17 lokalizacji SPA i wszystkie 17 lokalizacji cvstart.org kierowało link stopki Agentic Coding Design Patterns do wydania angielskiego, podczas gdy jedyna przetłumaczona etykieta — rosyjska, «Паттерны агентного кодинга» — obiecywała rosyjską książkę. Nowy applier
data-i18n-href(tego samego kształtu codata-i18n-title, ograniczony do bezwzględnych wartościhttps://) i kluczfooter.patternsUrlkierująrudo rosyjskiego wydania, a każdą inną lokalizację do angielskiego. Test regresji sprawdza tę niezmienniczość w obu kierunkach: przetłumaczony tytuł implikuje zlokalizowany URL. - SEEK migruje hosty, a transport odmawia przekierowań.
www.seek.com.au→au.seek.comiwww.seek.co.nz→nz.seek.com: strony szczegółów już zwracają 301, a obie pary hostów obsługują dziś API wyszukiwania v5 z kodem 200. Ponieważhttp-json.mjsustawiaredirect:'error'(obrona przed SSRF warta zachowania), dzień, w którym ścieżka API zacznie przekierowywać wpis AU/NZ na starym hoście, zakończyłby się błędem — a skoro na białej liście są tylko hostywww., nikt nie mógłby migrować.au.seek.cominz.seek.comsą teraz wALLOWED_JOBSTREET_HOSTS; stare hosty pozostają, więc istniejąca konfiguracja i już zbudowane linki nadal działają. Podszywające się hosty (au.seek.com.evil.com,au-seek.com) nadal są odrzucane. - Wiki: wiersz Agentic Practices na mapie dokumentacji Home był jedynym z dwunastu, który nie escape’ował
|wewnątrz[[…|…]], więc GitHub obciął komórkę — martwy link, ukryty opis. Jeden znak.
Uwagi
- Liczby bez zmian: 94 źródła (89 EN + 5 RU), 89 adapterów. Testy 3201 → 3210 (+5 lokalizacja linku stopki, +4 hosty SEEK).
- Nie do zamknięcia z zewnątrz, odnotowane, a nie zadeklarowane: Oracle Cloud (Akamai zablokował oba testy REST), przypięcie Personio i
appendWorkType(wymagają wpisu wportals.yml, a UI nie ma usuwania dla jednego z nich) oraz przypadki ciągów liveness (brak strony kontrolowalnej; 40 sond na żywo dało 12 żywych, 28 niejednoznacznych, 0 fałszywie wygasłych). - Pomoc ×17 wymienia teraz obie formy hostów dla
AU-MainiNZ-Main. Struktura nagłówków bez zmian: 32 H2 / 122 H3.
[1.237.0] — 2026-09-21
Parytet z rodzicem — career-ops main @ 93c4302b (VERSION 1.33.0, 75 commitów pobranych z career-ops-hq/main). Brak nowych źródeł tym razem: cztery odzwierciedlone poprawki, a dwie z nich po cichu gubiły tutaj oferty.
Naprawiono
Jobstreet / SEEK — każda australijska, nowozelandzka, singapurska, malezyjska i hongkońska oferta prowadziła do martwej strony. parseJobstreetItem budował URL szczegółów jako ${baseUrl}/id/job/${id} bezwarunkowo. Segment /id/ to nie ścieżka — to prefiks lokalizacji indonezyjskiej, który istnieje wyłącznie na hostach indonezyjskich. Każdy inny host platformy SEEK odpowiada 404 na /id/job/<id>. web-ui miało już dodane www.seek.com.au, www.seek.co.nz, sg.jobstreet.com, my.jobstreet.com i hk.jobsdb.com do ALLOWED_JOBSTREET_HOSTS, więc skan chętnie zwracał te oferty — każda wskazywała na 404. Ścieżka jest teraz kluczowana przez host: ID_LOCALE_HOSTS (id.jobstreet.com, www.jobstreet.co.id, jobstreet.co.id) zachowuje /id/job/, wszystko inne dostaje /job/, a niesparsowalny origin przechodzi do ścieżki wspólnej zamiast rzucać wyjątek. Dwa nasze własne testy zakodowały ten błąd — asercje sprawdzały hk.jobsdb.com/id/job/… i www.jobstreet.com/id/job/… — i zostały poprawione.
Oracle Cloud — krótka strona w środku listy kończyła przechodzenie i gubiła koniec tablicy. Warunek zatrzymania brzmiał listLen === 0 || listLen < PAGE_SIZE, ale ORC zwraca mniej wierszy niż limit w środku listy, bo część wierszy jest filtrowana po stronie serwera. Zmierzone u źródła na American Express: TotalJobsCount 454, strony po 200 / 199 / 54 — 199 zostało odczytane jako koniec, a ostatnie 54 oferty, 12% tablicy, nigdy nie zostały pobrane. Teraz pusta strona zawsze kończy przechodzenie; gdy najemca zgłasza sumę całkowitą, stronicowanie trwa aż do offset + PAGE_SIZE >= total; tylko najemca bez sumy do sprawdzenia kończy na krótkiej stronie. Odpowiada to szerszej konwencji, że API „może zwrócić mniej wyników niż żądano … nawet jeśli nie jest to koniec kolekcji” (Google AIP-158). hasMore pozostaje celowo ignorowane — niektórzy najemcy zwracają hasMore:false na każdej stronie tablicy liczącej 7000 ofert. Skoro krótkie strony nie kończą już przechodzenia, MAX_PAGES jest teraz jedynym zabezpieczeniem przed najemcą zgłaszającym fałszywą sumę, więc jest to pokryte własnym testem.
Liveness — fraza „This role is closed” nie była rozpoznawana, a fałszywe wygaśnięcie jest trwałe. Wzorzec brzmiał /this job (listing )?is closed/i, co pomijało równie częste sformułowania z role i position; na jednej tablicy u źródła zmierzono 111 ze 111 niepewnych ofert używających „role”. Rozszerzono do /this (?:job|role|position)(?: listing)? is closed\b(?!-)/i. Końcowe \b(?!-) to zabezpieczenie przed przymiotnikiem złożonym: samo \b odrzuca closedown, ale nadal dopasowuje się do prawdziwej prozy typu „This role is closed-loop control of the platform”, i to właśnie wyprzedzające sprawdzenie (lookahead) to zatrzymuje.
Liveness — job expired znajduje się teraz w miękkiej warstwie, która nie może przebić widocznego przycisku Apply. HARD_EXPIRED_PATTERNS jest sprawdzane przed testem elementu aplikowania, więc wszystko, co się tam znajduje, wygrywa z żywą ofertą. /\bjob expired\b/i fałszywie uruchamiało się na czterech prawdziwych kształtach żywej strony — wpisie karuzeli „Similar jobs”, chipie filtra „Hide job expired”, stopce FAQ i prozie closed-loop opisanej wyżej — bo klasyfikator otrzymuje tekst całej strony. Teraz znajduje się w SOFT_EXPIRED_PATTERNS, sprawdzanym po elemencie aplikowania i przed heurystyką strony z listą, zwracając expired_body_soft; goły baner „JOB EXPIRED” bez elementu aplikowania nadal wygasa. Ten kierunek ma znaczenie, bo fałszywe expired jest zapisywane w historii skanowania jako skipped_expired, a następnie filtr deduplikacji usuwa prawdziwą ofertę z każdego kolejnego skanu, bezterminowo, chyba że ustawiono scan_history.recheck_after_days.
Dodano
Personio — jawne personio: <slug> przypina najemcę. Wiele firm osadza swoją tablicę Personio jako iframe na markowej stronie kariery, więc careers_url wskazuje na własną domenę firmy, podczas gdy kanał znajduje się pod <slug>.jobs.personio.de; bez przypięcia takie tablice nie rozwiązują się do niczego. Slug jest ograniczony zestawem znaków przez zakotwiczoną białą listę (/^[a-z0-9][a-z0-9-]{0,62}$/i), a wynikowy URL wciąż przechodzi przez istniejący parser new URL(), sprawdzenie HTTPS i bramkę hosta PERSONIO_HOST_RE — przypięcie nigdy nie jest sposobem na dotarcie do innego hosta. Slug niosący ., /, @, :, .., biały znak, wiodący -, lub przekraczający limit 63 znaków etykiety DNS przechodzi do dzisiejszego zachowania api/careers_url. W przeciwieństwie do rodzica, wyrażenie regularne hosta w web-ui rozróżnia wielkość liter, więc przypięcie jest normalizowane przez new URL() — AcmeGroup rozwiązuje się do acmegroup.jobs.personio.de zamiast budować host, który jego własna biała lista i tak by odrzuciła.
Jobstreet — opcjonalne appendWorkType dopisuje do tytułu typy zatrudnienia z oferty, np. Strategy Consultant [Part time], dzięki czemu filtry tytułu i triage widzą typ zatrudnienia już w momencie skanowania. Domyślnie wyłączone; brakujące lub puste workTypes nic nie zmienia.
Uwagi
Liczby źródeł i adapterów bez zmian: 94 źródła (89 EN + 5 RU), 89 adapterów EN. To wydanie zmienia tylko liczbę testów, 3164 → 3201 (+13 jobstreet, +7 Oracle Cloud, +9 liveness, +8 Personio).
Rodzic usunął providers/telegram.mjs, konsolidując się na telegram-channel. web-ui rejestruje oba jako źródła widoczne dla użytkownika, więc to usunięcie nie jest naśladowane: zredukowałoby rejestr z 94 do 93 i po cichu zepsułoby konfigurację każdego, kto ma ustawione telegram. Do ponownego rozważenia wyłącznie jako celowe, zapowiedziane usunięcie.
jd-skill-gap.mjs zyskał nieskróconą formę nagłówka „what we are looking for” oraz usuwanie znaczników pogrubienia. web-ui przekazuje dalej ten skrypt zamiast go odzwierciedlać, więc poprawka dociera wraz z wdrożonym rodzicem i nie wymaga tutaj żadnej zmiany.
Nieportowane, z podanymi powodami: lib/latex-escape.mjs, browser-extract.mjs, openai-eval.mjs, update-system.mjs oraz scaffolder (web-ui ich ani nie odzwierciedla, ani się do nich nie odwołuje przez powłokę); TUI dashboardu w Go oraz formularz konfiguracji web/ (osobne powierzchnie); doctor.mjs i analyze-patterns.mjs (przekaźniki tylko do odczytu, których miękka odporność na błędy wchłania zmianę).
Cyrylicka rozbieżność forka \p{L} w providers/telegram-channel.mjs przetrwała scalenie z upstreamem nienaruszona i została zweryfikowana bajt po bajcie względem kopii sprzed scalenia.
[1.236.0] — 2026-09-18
Parytet z rodzicem — career-ops main @ 6a9c84c (VERSION 1.33.0, 128 commitów). Dwa nowe źródła i trzy odzwierciedlone poprawki — dwie z nich po cichu gubiły tutaj oferty.
Dodano
Dwa źródła skanera, 92 → 94 (89 EN + 5 RU). Python.org Jobs (pythonorg) czyta publiczny kanał tablicy ofert; atrybucja pracodawcy jest obowiązkowa, więc wiersz, którego tytuł nie wskazuje pracodawcy, jest odrzucany, zamiast być uzupełnianym nazwą wpisu portalu. Generalist World (generalist-world) scrapuje karty tablicy i głośno zawodzi na znaczniku, którego nie potrafi sparsować — zmieniony kształt karty rzuca wyjątek, zamiast być odczytanym jako pusta tablica, co jest tym trybem awarii, który czyni zescrapowane źródło niegodnym zaufania. Oba pojawiają się w filtrze Źródło na #/scan, oba są przypięte do hosta (zakotwiczone wyrażenie regularne, tylko HTTPS), a oba są sterowane od początku do końca zestawami z fałszywym transportem (43 i 36 przypadków).
Naprawiono
Stanowisko Workday otwarte w kilku miastach było odrzucane przez filtr lokalizacji. Endpoint listy Workday odpowiada na ofertę wielolokalizacyjną liczbą, tam gdzie każda inna oferta niesie miejsce: "53 Locations". To nie jest lokalizacja, a buildLocationFilter dopasowuje przez podciąg bez rozróżniania wielkości liter — więc stanowisko otwarte w Austin i 52 innych miastach nie pasowało do żadnego wpisu allow: [austin] i było odrzucane, podczas gdy to samo stanowisko wypisane pojedynczo przechodziło. Zmierzone u źródła w trzech najemcach: 53 z 291 ofert były placeholderami, więc to przypadek zwyczajny, a nie brzegowy. Prawdziwe miejsca oferty istnieją wyłącznie w dokumencie szczegółów CXS, więc każdy placeholder kosztuje teraz jedno dodatkowe GET względem niego, z limitem 200 na wpis — powyżej limitu placeholder pozostaje widoczny zamiast być sfałszowanym, bo nierozwiązana oferta nigdy nie może wyglądać jak rozwiązana. Nieudane lub pozbawione miejsca żądanie szczegółów zostawia ofertę dokładnie taką, jaką zwróciła lista: widoczne "53 Locations" jest uczciwe co do tego, czego nie udało się rozwiązać, podczas gdy wyczyszczona lokalizacja po cichu przeszłaby każdy filtr. To samo GET niesie również startDate, więc wzbogacona oferta jest datowana dokładnie, zamiast przez względną prozę endpointu listy ("Posted 30+ Days Ago" → undefined); wszystko, co nie jest gołym YYYY-MM-DD, jest pozostawiane bez zmian, zamiast być przepuszczanym przez Date.parse, którego nie-ISO-owy fallback jest zależny od implementacji.
Podany poziom nie zwija już dwóch rekrutacji w jedną powtórkę. "Insurance Specialist II" to własne oświadczenie pracodawcy, że ta rekrutacja nie jest siostrzaną wobec innej — inne widełki płacowe, zakres i numer rekrutacji pod jednym tytułem bazowym. Tokenizator tego nie widział: w.length > 3 odrzuca każdą cyfrę rzymską aż do VIII i każdą pojedynczą cyfrę, więc "Insurance Specialist" i "Insurance Specialist II" tokenizowały się identycznie, uzyskiwały idealny współczynnik Jaccarda, a detektor powtórek oznaczał drugą jako ponowne wystawienie pierwszej. role-matcher.mjs w web-ui w ogóle nie miał obsługi poziomów, więc ląduje tu cały mechanizm rodzica: poziomy są wyodrębniane, z cyframi rzymskimi i arabskimi zwiniętymi do jednej liczby ("Nurse II" i "Nurse 2" to to samo oświadczenie — i ta para wcześniej błędnie się różniła), dwa podane poziomy muszą się zgadzać, a poziom podany tylko po jednej stronie jest traktowany jako luźne przeredagowanie, chyba że każdy tytuł niesie też słowo, którego brak drugiemu — co jest dwiema rozbieżnościami, a nie jedną ozdobą.
Tablica Avature przypięta do filtra i tak przechodziła całą globalną tablicę. Interfejs wyszukiwania Avature generuje nieprzejrzyste parametry fasetowe (?42386=[812132] to filtr kraju), a operator, który przypina zawężoną tablicę w portals.yml, oczekuje, że skan przejdzie właśnie ją. resolveSearch odbudowywał URL jako ${origin}${path} i całkowicie odrzucał ciąg zapytania — więc każde żądanie, łącznie z pierwszym, przechodziło całą tablicę najemcy: więcej stron, więcej żądań i oferty, które operator celowo odfiltrował. Fasety jeżdżą teraz z każdym stronicowanym żądaniem, z naszym własnym jobOffset nałożonym jako ostatnim, więc przypadkowy faset o tej samej nazwie nigdy nie może przejąć stronicowania.
Bezpieczeństwo
devalue 5.8.1 → 5.9.2 (tranzytywnie przez astro), zamykając jedyny otwarty alert Dependabot — odmowę usługi na zniekształconym wejściu. Zależność tylko dla witryny; żaden kod uruchomieniowy się nie zmienił.
Uwagi
Nieportowane, każde z podanym powodem. Rodzic nadał lever 30-sekundowy, a manfred 25-sekundowy limit czasu wobec wspólnej wartości domyślnej 10 s — brak portu: transport skanowania web-ui dopuszcza już 60 s (DEFAULT_SCAN_TIMEOUT_MS), więc obie tablice mają tutaj więcej zapasu, niż daje ta poprawka tam. Podwojony prefiks careers- iCIMS też nie może tu wystąpić: web-ui pobiera origin najemcy wprost z api/careers_url i nigdy nie konstruuje hosta z nazwy najemcy; jego nowe przejście po hoście zapasowym to funkcja dla luźniejszej konfiguracji rodzica, a nie naprawa defektu. deutschebahn i manfred zyskały ponawianie przy przejściowym przerwaniu, co 60-sekundowy sufit web-ui czyni znacznie mniej palącym — odnotowane, a nie portowane, więc przyszły długi limit czasu ma już znaną pierwszą rzecz do wypróbowania. Wszystko inne w delcie 128 commitów to CLI, weryfikator, dashboard lub web/ (własny frontend rodzica): liveness-browser, check-jd-archive, verify-ats/verify-portals/verify-cv-facts, update-system, set-status, audit-portals, discover-ats, scaffolder, test-all, manifesty pluginów.
Rozbieżności forka ponownie zweryfikowane po pobraniu: cyrylicka poprawka \p{L} w providers/telegram-channel.mjs, własny providers/telegram.mjs forka, hermes w web/src/lib/clis.ts. Upstream career-ops-hq/main jest w pełni scalony (0 brakujących commitów). 3066 → 3164 testów; pomoc podaje teraz 94 adaptery (89 EN + 5 RU) we wszystkich 17 pakietach, a struktura nagłówków bez zmian: 32 H2 / 122 H3.
career-ops-ui v1.267.1 · page 2/10 · mirror of the project changelog for cvstart.org