Dziennik zmian

GitHub

Każda istotna zmiana, wydanie po wydaniu. Ten sam plik jest dostępny w repozytorium i przetłumaczony na wszystkie 19 języków.

[1.267.1] — 2026-11-04

Naprawiono

  • Naprawa pociągu release’ów (bramki CI v1.267.0) — łańcuch zliczania testów w PROJECT-CONTEXT nie urywa się już na głowie v1.267.0 (format strzałki, który dopasowuje eval grader), prompty QA są zreorganizowane (jeden żywy prompt na release, v1.266.0 zarchiwizowany), a pokrycie per plik podniesiono ponad ratchet 98/90: renderer salary w applicantpro traci nieosiągalny fallthrough (salaryRangeOf dowodnie daje undefined, {min}, {max} lub {min,max}), jednostronne gałęzie ≥/≤ są teraz przypięte przez przepływ fetch, a zestaw board-response-cache przypina ominięcie no-store, 304 dostarczone przez wywołującego wobec niezapisanej tablicy oraz wyrzucanie przy MAX_ENTRIES.
  • Testy: licznik na żywo to 7395 (suity fali v1.266.0/1.267.0 niosą więcej speców, niż śledziły wcześniejsze notki — łańcuch jest ponownie zakotwiczony na zmierzonym poziomie: 7392 po fali, + 3 testy bramki w tej łatce); pokrycie 98.51 linii / 90.35 gałęzi.

Uwagi

  • Tag v1.267.0 pozostaje wskazujący na czerwony commit merge’a — nie jest przestawiany (serwer odrzuca przestawione tagi); v1.267.1 jest nośnikiem wdrożenia.

  • Naprawa patchowa pociągu v1.267.0: bramki CI zielone, drzewo kodu nie zmieniło się merytorycznie.

[1.267.0] — 2026-11-04

Dodano

  • Cztery nowe źródła skanowania — GermanTechJobs, Darwinbox, Keka, ApplicantPro/isolved (rejestr 125 → 129 = 124 EN + 5 RU · 124 adapters) — druga fala parent-sync przeciw career-ops @ 7d8feb6d (87 commitów upstream). GermanTechJobs (#6346): RSS całej tablicy na germantechjobs.de/rss (~626 pozycji w jednym żądaniu); pracodawcą jest ostatni segment " @ " tytułu — tytuł bez takiego segmentu jest odrzucany, nigdy nie księgowany pod tablicą; wybór wyłącznie przez jawny provider:. Darwinbox (#6416): JSON alljobs bez autoryzacji pod <tenant>.darwinbox.in, id firmy pochodzi z URL-a careers, stronicowany marsz POST-em (50/stronę, max_pages 20/200) ze stopem na krótkiej stronie wyliczanym z własnego licznika wierszy źródła. Keka (#6199): dwa żądania — powłoka careers z redirect:'manual', której skrypt nazywa UUID feedu (nieznany tenant odpowiada przekierowaniem 302 na TenantNotFound.html i czyta się jako nazwany 404), potem cały otwarty inwentarz w jednej tablicy embed-jobs. ApplicantPro / isolved (#6252): numeryczny domainId z bootstrapu, potem {success, data:{jobs, jobCount}}; jobCount > rows ostrzega, że lista jest niekompletna; opt-in applicantpro: { fetchDetails: true } wzbogaca z JSON-LD w rytmie 250 ms.
  • Ponowne użycie odpowiedzi tablic przez ETag (#6105) — w obrębie jednego skanu odpowiedź tablicy pobrana w ostatnich 15 minutach jest używana jak leży, a starsze są rewalidowane przez If-None-Match (304 zachowuje body); klucz cache obejmuje metodę + URL + nagłówki poświadczeń + body, nakładające się odczyty zwijają się w jedną trwającą obietnicę (in-flight promise), a CAREER_OPS_HTTP_CACHE=0 / _TTL_MS to nadpisują. Cache w pamięci, per przebieg skanu (web-ui nie ma kontraktu cache na dysku) — odchylenie odnotowane.

Naprawiono

  • Daty na czterech tablicach (#6274) — remoteok, remotive, workingnomads i IBM zwracają teraz datę publikacji, więc filtr «Posted within» tam działa; naiwny znacznik czasu remotive jest normalizowany do UTC (jego per-maszynowy błąd liczenia wieku działał na żywo), a _source IBM faktycznie żąda dcdate.
  • Błędnie wpisany klucz portals.yml jest odrzucany (#6107) — skan EN rzuca teraz nazwany błąd (plik + klucz + sugestia najbliższego klucza, Levenshtein ≤ 2) przed jakimkolwiek pobraniem, zamiast milcząco ignorować titel_filter:.
  • getro idzie dalej za starym przypiętym ogłoszeniem featured (#6406) — przypięta nieaktualna oferta wciąż jest odrzucana, ale już nie kończy paginacji; przejście zatrzymuje się na prawdziwej krótkiej stronie.

Uwagi

  • Świadomie nie zrobione: filtr widzianych skanera RU nie jest świadomy języka, a jego ścieżka parsowania portals nie przechodzi przez bramkę błędnych kluczy (hand-offy zapisane w specyfikacji fali — żadna tablica RU nie zwraca jeszcze wierszy per język); remoteok zachowuje swój ciąg daty z offsetem zamiast normalizować do UTC (jego żywy kształt jest deterministyczny). Tests 7096 → 7243; Playwright 173 pass / 0 fail / 1 opt-in skip; rejestr 129 = 124 EN + 5 RU · 124 adapters (wszystkie bramki licznikowe regenerowane z żywego rejestru).

[1.266.0] — 2026-11-01

Dodano

  • Wersje językowe personio przestają zjadać się nawzajem (CAR-223: parent #4789 + #5044 + #5285) — odroczony stos, wykonany jako osobne wydanie. Strona skanu (#4789): scan_history.dedup_include_language: true (ścisły opt-in — OFF jest identyczny bajt w bajt) sprawia, że wersje językowe jednej oferty przeżywają dedup dzięki maszynerii wariantów historii widzianych (languageFormsFromUrl / recordUrlVariant / isUnseenLanguageVersion); klucz kanoniczny obcina parametry language/lang/locale. preferred_languages (#5285): porządkuje wiersze wersji oferty od preferowanych (stabilnie, przy remisie kolejność providera) — niezależnie od przełącznika (OFF zostawia preferowaną wersję, ON zostawia każdą wersję w tej kolejności), z portem validatePreferredLanguages z validate-portals. personio fan-out (#5044): strona careers jest pobierana bez wymuszania ?language=en (własny ?language=xx tenanta jest honorowany) i zwraca jeden wiersz na wersję językową z URL-ami language + ?language=<code>; dedupIncludeLanguage dodaje pobrania per język (limit 5, z tempem); fallbacki /xml i job-link bez zmian. recruitee dostaje tę samą emisję language + preferred_languages (w opts albo wpisie). Wspólne helpery żyją w server/lib/language-preferences.mjs.

Uwagi

  • Hand-offy odnotowane, świadomie nie zrobione: filtr widzianych skanera RU nie jest świadomy języka i żadna tablica RU nie zwraca jeszcze wierszy per język; kliencki mirror url-key.js i podpięcie walidacji w routes portals pozostają otwarte. Tests 7096 → 7203; rejestr bez zmian 125 = 120 EN + 5 RU · 120 adapters.

[1.265.0] — 2026-11-01

Dodano

  • Dwa nowe źródła skanowania — Apple i Bulldogjob (rejestr 123 → 125 = 120 EN + 5 RU · 120 adapters) — fala parent-sync przeciw career-ops @ fe857ecf. Apple (jobs.apple.com, #5496 + #6196): strona to aplikacja React Router SSR bez użytecznego API JSON, więc źródło czyta blob hydratacji zwykłej trasy wyszukiwania (window.__staticRouterHydrationData); odkrywanie prowadzi wpis (apple.queries z sortowaniem po trafności + osie apple.teams, brak domyślnych — wpis bez żadnej rzuca błędem), strony ogranicza max_pages (domyślnie 2, sufit 50) z pauzą 200 ms, każdy segment URL jest kodowany odpornie na surrogaty, a oferta oznaczona przez Apple jako PIPE niesie w snippecie wskazówkę «może być talent pipeline» — nic na tej podstawie nie jest filtrowane. Bulldogjob (bulldogjob.pl, #6253): polski tech board też nie ma API JSON — listingi niosą __NEXT_DATA__ (50/stronę, totalCount); careers_url wpisu to wyszukiwanie zbudowane na stronie (filtry żyją w ścieżce), każde żądanie niesie jawny /page,N, a przejście zatrzymuje się na krótkiej stronie, zgłoszonym totalu lub max_pages (domyślnie 25, sufit 100) z etykietą obcięcia na częściowych tablicach.
  • Rework paginacji IBM (#6273) — stały marsz po 600 rekordów staje się max_pages (domyślnie 20, sufit 300, nadpisanie na wpisie) z pauzą 200 ms między stronami i retry per strona przez fetchJsonWithRetry; nieudana pierwsza strona rzuca, nieudana późniejsza zachowuje zebrane i nazywa stronę, a tylko pełna strona na własnym suficie wpisu ostrzega «raise max_pages».

Naprawiono

  • justjoin datuje oferty wg lastPublishedAt (#6254) — publishedAt kandydackiego API przesuwa się przy każdym odświeżeniu przez pracodawcę, więc większość tablicy nosiła dzisiejszą datę i max_posting_age_days przepuszczał oferty sprzed tygodni; teraz wygrywa wcześniejsza data publikacji, z fallbackiem gdy jej brak lub nie parsuje się.
  • jobvite składa wiersze dzielące jeden posting URL (#6127) — publiczny feed zwraca wiersz <job> na miasto dla jednego detail URL; parser trzymał pierwsze miasto, a resztę liczył jako duplikaty. Teraz rodzeństwo wnosi tylko lokalizacje, sklejane · w kolejności feedu, pierwszy tytuł/data zostaje, a remote jest przeliczane na złożonej lokalizacji.
  • Liveness: rung UltiPro (#6090) — UKG nie ma per-posting endpointu JSON i odpowiada 200 także na zamknięte, więc wszystkie 57 zamkniętych ofert UltiPro czytało się uncertain. Strona detalu wkrada rekord: OpportunityIsClosed true/false → expired/active, notice «opportunity unavailable» → expired, reszta zostaje przeglądarce. Baner Built In «Sorry, this job was removed» staje się hard-expired (#6336) — strona zachowuje pełny JD i kontrolkę APPLY; teraz wygrywa baner, a sąsiedni badge «Job removed» bez «sorry» nie łapie się.

Uwagi

  • Świadomie nie zrobione: parent-side połowa poprawki jobvite o kompilatorze lokalizacji scan.mjs (web-ui dokumentuje kompilator USPS jako no-port) i pole note rodzica dla wskazówki PIPE od Apple (job shape web-ui nie ma note; jedzie w snippecie). Tests 7096 → 7135 (+39); Playwright 173 pass / 0 fail / 1 opt-in skip; coverage gate ≥ 98/89; rejestr 125 = 120 EN + 5 RU · 120 adapters (wszystkie bramki licznikowe regenerowane z żywego rejestru).

[1.264.3] — 2026-11-01

Naprawiono

  • Fala utwardzenia rate-limitów (LOW №1–3 z przeglądu REVIEW-2026-10-31-v1.264.1) — writeRateLimit() (express-rate-limit@7.5.1, 60 req/min route×IP, 429 JSON + Retry-After) obejmuje teraz wszystkie 47 mutujących endpointów (było 2): 9 guardów llmRateLimit o złym zakresie zastąpiono (/api/config — przepisywanie .env!, PUT /api/batch, /api/batch/merge, outcome, followup/seed, assessments, stats/snapshot, mock-interview/save, networking/save), 3 nałożono przed kubełkiem LLM na kosztownych ścieżkach (/api/evaluate, /api/deep, /api/auto-pipeline), a 33 nagich rejestracji podpięto (edytory CV/profile/modes, wszystkie zapisy trackera, pipeline POST/restore/DELETE, jds, wszystkie 7 /api/run/* jedną edycją pętli, posting-guard, Playwright-PDF inline, portals toggle/health/track, discover, reports, export/docx, two-pager, career-plan, memory oraz trzy ścieżki DELETE). /api/apply-helper zostaje nagie na allowliście (czyste obliczenia lokalne, przypięte); 16 czysto-LLM-owych ścieżek z założenia trzyma warunkowy kubełek LLM. Tripwire kompletności (tests/rate-limit-coverage.test.mjs, red-first przy 27 nagich) wywala CI przy każdej przyszłej mutującej rejestracji bez throttlingu.
  • TRUST_PROXY jako opt-in + ponownie uzbrojone walidacje (LOW №1–2 z przeglądu) — app.set('trust proxy', N) honoruje liczbę hopów ze zmiennej środowiskowej TRUST_PROXY (nigdy boolean true — kluczowałoby to po lewym, kontrolowanym przez atakującego końcu XFF); domyślnie nieustawiona, więc loopback zachowuje udokumentowaną, kluczowaną gniazdem (socket) degenerację per-route. validate: false staje się celowym writeValidateConfig(): z walidacji wyłączono wyłącznie xForwardedForHeader (XFF od Caddy jest ignorowany z założenia bez trust proxy), każda inna walidacja — łącznie z trustProxy — znów jest głośna, więc przyszła pomyłkowa konfiguracja trust proxy: true ujawni się jako ERR_ERL_PERMISSIVE_TRUST_PROXY zamiast milczeć. Własny keyGenerator usunięto świadomie: express-rate-limit wiąże swoje walidacje proxy z domyślnym generatorem kluczy, a izolacja per-route pozostaje bez zmian (jeden MemoryStore na wywołanie fabryki).
  • Informacja zwrotna kopiowania na cvstart.org cofa się po 2 s (CAR-141) — stan «Скопировано ✓» utrzymuje się teraz wymagane kryterium akceptacji 2 sekundy (było 1,5 s), przypięte red-first w tests/site-copy-feedback.test.mjs. To zamyka ostatnie kryterium CAR-141 możliwe do zamknięcia przez agenta; odświeżenie wideo demo pozostaje odroczone przez właściciela (decyzja 2026-11-01).

Zmieniono

  • Paczki pomocy mówią o 19 językach (×19) — zdania w §19 „Localizing the app” i §32 „Run it from OpenWorker” nie są już o dwa języki w tyle: każda paczka podaje teraz 19, wymieniając தமிழ் i Tiếng Việt w swoim własnym stylu wyliczania (ar używa zapisu słownego «التسع عشرة»), a własny relikt «cả-17» w §32 vi.md również poprawiono. Bramki struktury (33 H2 / 125+ H3) stabilne bajt w bajt.
  • Higiena stanu — AGENTS.md podaje v1.264.2 / 7082 testów (było v1.86.x / 1566); PLAN.md oznacza wydania 1–7 jako Shipped, a jego akapit o ship trainie mówi docs ×19; komentarz w StatsBar.astro opisuje teraz, co faktycznie przechowuje facts.adapters (123 = łączna liczba sources, historyczna nazwa klucza zostaje dla konsumentów); nagłówek i18n.js mówi o 19 językach; prompt QA v1.264.2 wozi prawdziwe pokrycie (98.45/90.05) oraz arytmetykę Playwrighta (176 = 174 harness + 1 opt-in skip + 2 zestawy skryptowe).

Uwagi

  • Świadomie nie zrobiono: fala parent-sync według zapisanej listy portów zostaje w BACKLOG-u — fork musi najpierw zsynchronizować się z upstreamem co najmniej do a9476866 (7 z 10 commitów z listy portów nie ma jeszcze w lokalnym drzewie rodzica; IBM/UltiPro/Bulldogjob/apple wycenione na S–M, language-dedup personio odroczony do osobnego wydania). Ponowne nagranie wideo demo CAR-141 jest świadomie odroczone przez właściciela («видео не надо пока», 2026-11-01).
  • Tests 7082 → 7096 (+9 tripwire pokrycia + 5 trust-proxy); Playwright 173 pass / 0 fail / 1 opt-in skip (+2 piny chevronów w istniejących przypadkach); pokrycie 98.46 linii / 90.10 gałęzi; evals 14/0/1skip; rejestr bez zmian: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.264.2] — 2026-11-01

Naprawiono

  • Nagłówki grup w sidebarze dołączają do kontraktu ucinania (CAR-219) — etykiety przełączników grup (.nav-v2-toggle > span) ucinają się teraz wielokropkiem i niosą zlokalizowany tooltip tym samym mechanizmem syncLabelTitles() co elementy nawigacji z CAR-203; chevron nigdy się nie kurczy, przełącznik pozostaje klikalny, lustrzane odbicie RTL trzyma. Pin red-first w tests/nav-v2.test.mjs (+1 → 7082 testy).

Zmieniono

  • Treść cvstart.org trafia na produkcję we wszystkich 19 językach (CAR-220) — meta.helpDesc, helpTeaser.c1.desc i faq.a2 są przetłumaczone w każdej lokalizacji strony (w v1.264.1 były celowo wyłącznie po angielsku); GitHub Pages wysłał podniesioną treść na żywo na cvstart.org.
  • Higiena backloga i przeglądu (CAR-221/222) — sześć pozycji «port when merged upstream» jest zamkniętych: wszystkie siedem PR-ów upstream scalonych, cztery pozycje były już sportowane, dwie leżą po stronie rodzica. docs/reviews/REVIEW-2026-10-31-v1.264.1.md trafia do repo (0 HIGH / 0 MED, trzy LOW-zastrzeżenia zapisane w BACKLOG-u), a lista portów parent-sync zostaje zapisana (6 PORT / 3 VERIFY / luka apple-source; ogon upstream: 118 commitów @ VERSION 1.38.0).

Uwagi

  • Poprawka stemplowania mirrorów changelogu (92a05fcf) jedzie w tym tagu: każdy stronicowany mirror na cvstart.org nosi teraz wersję wydania, która go wygenerowała, więc grader site-build-after-fanout w końcu ćwiczy swoją prawdziwą logikę zamiast ją pomijać.
  • Świadomie nie zrobiono: throttling pozostałych mutujących POST-ów (LOW №3 z przeglądu) oraz sprzęgnięcie kubełków z trust proxy — zapisane w BACKLOG-u na kolejną falę utwardzania. CAR-141 (wideo demo) pozostaje za właścicielem.
  • Tests 7081 → 7082 (+1 pin CAR-219); Playwright 176; rejestr bez zmian: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.264.1] — 2026-10-31

Naprawiono

  • Pigułki w sidebarze zgrabnie ucinają długie zlokalizowane etykiety (CAR-203) — span etykiety nawigacji jest teraz pełnoprawnym obywatelem flexa (min-width: 0 + overflow: hidden + text-overflow: ellipsis + nowrap w v2-nav.css), a syncLabelTitles() w nav-v2.js odbija zlokalizowaną etykietę do tooltipa przez ten sam klucz data-i18n (zero nowych kluczy i18n) — długi «Профинансированные компании» jest znowu czytelny po najechaniu, zamiast być twardo ucinany przez overflow: hidden wiersza. Cel dotykowy 44 px, malowanie stanu aktywnego i lustrzane odbicie RTL pozostają nietknięte; pin red-first w tests/nav-v2.test.mjs.
  • Jeden sufit 480 s dla ocen we wszystkich językach (CAR-218) — remote-QA v1.264.0 przyłapała ulotne oceny 502 · 300 s · 0 ch na es i zh-CN (punktowy rerun przechodził, ale ściana była realna). EVAL_TIMEOUT_MS to teraz 480_000, a evalTimeoutMs(lang) zwraca tę wartość bezwarunkowo — dziedziczą GEMINI_EVAL_TIMEOUT_MS i auto-pipeline. Budżet tokenów świadomy języka z CAR-174 (16384 / 32768) pozostaje jedynym podziałem per-locale.

Zmieniono

  • FAQ na cvstart.org nosi dokładne liczby źródeł (CAR-217) — fraza {sources} źródeł portali z ofertami pracy: {sourcesEn} międzynarodowych plus {sourcesRu} rosyjskich jest podstawiana z facts.json, generowanego z żywego rejestru (123 = 118 EN + 5 RU), więc liczby nie mogą już nigdy dryfować; języki wciąż na starszym sformułowaniu ~{adapters} zachowują zaokrąglanie przez adaptersRounded. Podniesienia kopii EN jadą w pakiecie (meta.helpDesc, helpTeaser.c1.desc, faq.a2 wymieniają menu komend, pipeline z grupowaniem i undo oraz tracker-kanban).

Uwagi

  • Świadomie nie zrobiono: podniesienia kopii i18n strony (meta.helpDesc / helpTeaser.c1.desc / faq.a2) zostają w tym wydaniu wyłącznie po angielsku — pozostałe języki trzymają poprawne, lecz bardziej ogólne sformułowania do następnej fali dokumentacji (ich faq.a7 dostaje placeholdery dokładnych liczb tam, gdzie przetłumaczone). CAR-141 (wideo demo) pozostaje za właścicielem; zastąpiona gałąź car136/m141 została usunięta, a jej pomysły zapisano w zadaniu Linear (do odzyskania przez tag archive/car136-m141).
  • Tests 7041 → 7081 (pin CAR-203 + przepisane piny CAR-218); Playwright 176; rejestr bez zmian: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.264.0] — 2026-10-31

Dodano

  • Inline-edycja statusu w trackerze — odznaka statusu każdego wiersza #/tracker stała się kompaktowym <select> kanonicznych etapów (z GET /api/tracker/stages, żadnej zahardkodowanej whitelisty). POST /api/tracker/status wywołuje kanoniczny set-status.mjs rodzica pod lockiem applications.md (whitelist stanów przez states.mjs, przekaz --dry-run/--note, fail-soft 502 z zsanityzowanym szczegółem, spawn przez tablicę argv). Sukces aktualizuje wiersz w miejscu (klasa tone + liczniki zakładek, focus zachowany); porażka cofa wartość i pokazuje toast. Wiersze, których relay nie potrafi zaadresować — ręcznie wpisany nieznany status, sentinela backfill # — zachowują odznakę read-only (poprawki LOW z route-review; recenzent: żadnych HIGH/MED).
  • Ostrzeżenia serwera na każdej stronie AI — evaluate, deep, auto-pipeline (strona i modal), career-plan, market, cv-studio (humanize + tailor) pokazują teraz tablicę warnings serwera (ucięcie po tokenach wyjścia, dryf języka, korekty dat) jako pasek badge-warn (role="status"); modal auto-pipeline nie gubi już ostrzeżeń z ramki done. Nowy klucz llm.truncatedNotice ×19.
  • Fala pokrycia (+111 testów) — routes/map.mjs 100/94.9, geocode.mjs 96.3/92.9, content.mjs 99/84.9, networking.mjs 96.4/89.1, sources/habr.mjs 100/98.2 (nowe tests/cov-*-routes.test.mjs ×3, tests/sources-habr.test.mjs); dolna granica po gałęziach utrzymana na ≥ 90 %.
  • Paczka zamknięcia Linear CAR-191…216 (docs/reviews/2026-10-30-linear-car191-216-closure-bundle.md) — gotowy do wklejenia close-out dla właściciela z SHA commitów i komentarzami-dowodami dla każdego CAR.

Naprawiono

  • Skan-źródło Trudvsem — pusta strona (results: {}, także „za końcem”) już nie zabija całego skanu (czyste zero wierszy); koperty błędów API (HTTP-200 z status: 500) rzucają wyjątek z tekstem samego API; paginacja idzie po record-offsetach (było po indeksie stron — strony po cichu się dublowały, ~52 wakaty zamiast setek); przejście zatrzymuje się przed strefą awarii API przy głębokich offsetach (offset × limit ≥ 10000). Zweryfikowane na żywo end-to-end.
  • habr — tytuły/firmy są oczyszczane z tagów po dekodowaniu encji (paritet z hh.mjs): &lt;script&gt; w tytule karty nie dociera już do wierszy skanu jako żywy markup; legalne >> w tytułach przeżywa.
  • PUT /api/profile (ścieżka raw) — blok candidate: bez niepustego full_name jest odrzucany, tak samo jak na ścieżce scalania pól (wcześniej zapisywano full_name: null).
  • Prawdomówność podpowiedzi — .doc usunięte z listy accept wgrywania CV i z cv.uploadHint ×19 (parser nigdy go nie wspierał); config.openaiModelHint ×19 wymienia gpt-5 (serwer mapuje każdy id *-codex na niego); config.anthropicModelHint ×19 i domyślny model Anthropic odzwierciedlają teraz tiery rodzica — domyślnie claude-sonnet-5-5, premium claude-opus-5-5.
  • Link do dokumentacji Claude Code → code.claude.com (stary URL docs.anthropic.com/en/docs/claude-code wywala TypeErrors w bramce linków).
  • help ×19: usunięto punkt Row-density (przełącznik opuścił UI w v1.263.0) i naprawiono 18 rodzin zepsutych spanów **bold** — plus klasa przecieku renderera poprawiona ×19 (drugi pusty wiersz po każdej tabeli przed akapitem; glif pipe poza pogrubionymi komórkami): 0 literałów ** w renderze we wszystkich 19 paczkach pomocy.

Uwagi

  • Domyślny model Anthropic zmienił się na claude-sonnet-5-5 (standardowy tier rodzica). Wdrożenia polegające na starym cichym domyśle (claude-sonnet-4-6) aktualizują się automatycznie — przypnij ANTHROPIC_MODEL w .env, żeby zostać przy poprzednim.
  • Świadomie nie zrobiono: dwa LOW-zastrzeżenia recenzji pozostawione otwarte celowo (inline select nie odwzorowuje degradacji movesReady kanbana — uczciwy toast przy każdej porażce to wybrane zachowanie; gałąź code: 'timeout' pozostaje pokryta kontraktem fake-writer, a nie testem >30 s). CAR-141 (wideo demo) pozostaje za właścicielem.
  • help ×19 dostały po-release’owy przegląd prozy (punkt gęstości usunięty, klasa przecieku renderera poprawiona) na main po wydaniu v1.263.0 — to wydanie to pierwszy tag, który go wozi.
  • Również w tym tagu: infrastruktura chipa dowodów (parsery raportów + odznaki widoku), runner fix-report-links (POST /api/runners/report-links, karta «Napraw» na #/health) oraz szacowanie/potwierdzanie kosztu batcha z zapisem usage — trafiły na main między cięciem gałęzi a tagiem.

Tests 6905 → 7041 (+136) · Playwright 176 (173 pass / 1 opt-in skip) · pokrycie 98.5 % linii / 90.1 % gałęzi · rejestr bez zmian: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.263.0] — 2026-10-30

Dodano

  • Warstwa wypolerowania animacji — nowy motion.css (ostatni arkusz aplikacji): wejścia modali/popoverów (scale .97 + wygaszanie, 130–180 ms), springowe pojawianie toastów + miękki stan odchodzenia, springowe wciśnięcie przełącznika motywu, scale(.97) przy wciśnięciu chipów/zakładek, stagger-infrastruktura (kroki 50 ms, limit 12), wygaszanie .page-enter przy zmianie trasy (router), przejścia focus-halo na chipach/zakładkach. Każda reguła jest bezpieczna przy prefers-reduced-motion (ruch spada do none, opacity/kolor zostają).
  • Poprawność na urządzeniach dotykowych — 68 reguł hover-uniesienia było niechronionych: urządzenia dotykowe zostawały z „zawieszoną” uniesioną kartą po tapnięciu. Wszystkie transform-hovery są teraz ogrodzone @media (hover:hover) (neutralizator motion.css), a uniesienie karty dotyczy tylko faktycznie interaktywnych kart (.card:has(a), a.card, button.card, [role=button].card) — koniec z fałszywą affordancją na statycznych kartach.
  • A11y: każda kontrola ma nazwę programistyczną. Nowy helper A11yDump nazywa wszystkie 16 readonly-zrzutów wyjścia LLM; 12 pól z samym placeholderem (CV Studio ×6, config ×2, wyszukiwanie w skanie, select oceny w trackerze, notatka outcome, edytor planu, URL auto-pipeline, bug report) dostało aria-label; bramka a11y-form-wires wymaga tego teraz dla całej klasy (było 26 nienazwanych miejsc, jest 0 + allowlist z udokumentowanymi powodami).

Naprawiono

  • #/scan: przyklejony nagłówek tabeli nie maluje się już na wierzchu wyszukiwania w topbarze po przewinięciu pod niego (z było równe topbarowi, wygrywał późniejszy DOM — teraz token-derived poniżej niego); inputy «Зарплата от/до» są znowu normalnych rozmiarów (reguła flex .v2-scan-bar .input przeciekała do kolumnowego flexa popovera i ustawiała flex-basis 200 px jako WYSOKOŚĆ — teraz scope przez > + strażnik popovera); przycisk przełączania gęstości usunięty decyzją właściciela (mechanika zostaje, klucze i18n usunięte ×19).
  • Utwardzenie deploy workflow (F1–F6): input provider walidowany pod kątem zestawu znaków przed każdym wstawieniem do shella; diagnostyka hermes redaguje wartości (filtr kluczy niewrażliwy na wielkość liter + maskowanie wartości + ucinanie do 80 znaków na wszystkich trzech ujściach, maskowane są też ?token=); krok hermes respektuje inputs.app_dir; public_url przepuszczany tylko po https; strażnik antydowngrade’owy ma 6 wykonywalnych pinów (refy bez domyślnych, strażnik przed Deploy, ścisły regex refów).
  • Ogon recenzji, red-first: powrotna podróż backslasha przy imporcie CSV (ponowny import znowu się deduplikuje), wycinanie <head> w cv-voice 4827 ms → 13 ms, statedYearsMin liczone leniwie, TOCTOU capture w posting-guard, wildcard MiniMax CN, pomijanie tokenów Deela, strażniki rozmiaru import pickera przed odczytem. Modal importu: uzbrojony nav guard, input pliku usuwany przy cancel, strzeżony odczyt duplikatów, num przez reduce.
  • Batch UX od właściciela: pionowy rytm hero dashboardu (dzieci inline-level sklejane w jeden line box); przesunięcie aktywnego wiersza spisu treści pomocy o −8 px (wierszowy inline gutter + kolumna numerów); mobilny drawer (widoczny przycisk ✕, reset scrollTop, fantomowe wygaszanie –paper ograniczone do .has-hud); strona docs-assistant nie przepełnia się już przy długim URL w odpowiedzi (łańcuch grid min-width + overflow-wrap: anywhere); «Ostatnie» wyjaśnione (podpowiedź) + czyszczalne; Save w career-plan uzbraja się ponownie po nieudanym wczytaniu; URL-prefill w evaluate nie pali już wywołania LLM na placeholderze wklejania; Enter w auto-pipeline respektuje kompozycję IME.
  • Kontrast (audyt WCAG, 296 par): gradient docs-fab 2.43 → 6.4:1, para toast.success → ok-soft (1.75 → AA w ciemnym), flip banner btn-dark → --ink, jasne warianty scan-logbtn/reposts-badge/fab-chip/close, oraz obramowania kontrolek formularzy do 3:1 (--cv3-input-line, WCAG 1.4.11 — było 1.2:1).
  • Przegląd wizualny: pusty stan trackera to karta na całą szerokość (wcześniej przycinany wewnątrz tabeli 760 px przy 390); linia konsoli skanu dostaje wielokropek zamiast połowicznego ucięcia; pływający chat-FAB nie zakrywa już treści przy 390 (cel 44 px, inset 12); pusty stan «Application statuses» na dashboardzie trzyma się wzorca v2-empty; podpowiedź «?» w stats dostaje separator + cel 44 px; zakładka Input w career-plan wyjaśnia, gdzie ląduje wynik; markdown §1 pomocy (18 zepsutych spanów pogrubienia).

Zmieniono

  • Akcent: niebieski → karmazynowoczerwony (prośba właściciela, spójny z logo, hue 15) — 5 tokenów cv3 × 3 bloki motywu; tekst bąbelka czatu docs-assistant jedzie przez --accent-ink (wcześniej literał #fff, 2.39:1 w ciemnym); podkład funded jedzie przez --accent-soft. Danger zostaje przy hue 25 ze swoimi treatmentami.
  • Dokumentacja: licznik w tabeli testowania README ×17 (dryf ery v1.248), §1 pomocy + 18 spanów markdown, «118» w pomocy fr/it/ta, ceny dostawców CHECKED_ON 2026-10-30, fakty HANDOFF/CONTEXT/TRACEABILITY.

Uwagi

  • Świadomie nie zrobiono: przeróbka przeglądu szkieletów zostaje na boku (kontrakt car112 przypina obecne wygaszanie dosłownie); crossfade ikony przełącznika motywu zostaje zamianą display (obserwuje go kontrakt Playwright theme-toggle); skala .btn:active nie została zduplikowana (właścicielem jest app.css); stagger animacji to wyłącznie infrastruktura — kafelki dashboardu przyjmą go później; proza pomocy ×19 (wzmianka o gęstości, markdown §1, «118») jedzie następnym fan-outem.
  • Pełne dowody remote-QA: punktowy rerun ja zielony (376 s / A–G ✓) na v1.262.4; en/it zielone wcześniej, w erze token-dense.

Tests 6869 → 6905 (+36) · Playwright 176 · pokrycie 98.4 % linii / 89.9 % gałęzi · rejestr bez zmian: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.262.4] — 2026-10-30

Naprawiono

  • ja dołącza do języków token-dense ewaluacji (ja → limit 32768 tokenów + zegar 480 s). Punktowy rerun pięciu locale na prodzie v1.262.3 rozdzielił cztery nocne timeouty 502 · 300 s · 0 ch na przejściowe i deterministyczne: ar (250 s), ko (291 s) i zh-CN (259 s) przeszły swoje reruny, jednorazowy dryf językowy ru nie powtórzył się — ale ja dwukrotnie uderzyła w standardowy limit z zerowym wyjściem (pełny przebieg ×19 40981578549 i punktowy 41012725839). Ta sama klasa kształtu co it/pl. Pin red-first: evalMaxTokens('ja') = 32768, evalTimeoutMs('ja') = 480_000, pozostałe locale zachowują 300 s.

Uwagi

  • Świadomie jednocelowy patch: poprawka ja to jedyna zmiana, jaką niesie to wydanie — nie wozi niczego więcej. ar/ko/zh-CN pozostają na standardowym limicie przy dzisiejszych danych (przechodzą; nocne awarie były przejściowymi problemami z obciążeniem providera), a dryf ru okazał się jednorazową wpadką generacji.

Tests 6868 → 6869 (+1) · Playwright 176 · rejestr bez zmian: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.262.3] — 2026-10-30

Naprawiono

  • pl dołącza do języków token-dense ewaluacji (pl → limit 32768 tokenów + zegar 480 s). Pełny remote-QA na prodzie v1.262.1 przyłapał polską ewaluację umierającą na standardowym limicie — 502 · openrouter · 300 s · 0 ch — a punktowy rerun wysłany z v1.262.2 odtworzył to dokładnie (przebiegi 40960568766 i 40968958062): 18/19 locale przeszło A–G, it skończyła na 302 s wewnątrz token-dense zegara 480 s, a pl dwukrotnie uderzyła w ścianę z zerowym wyjściem. Deterministyczny timeout, nie flake — ta sama klasa kształtu, która przeniosła it w v1.262.1. Pin red-first: evalMaxTokens('pl') = 32768, evalTimeoutMs('pl') = 480_000, 18 standardowych locale zachowuje 300 s.

Uwagi

  • Świadomie jednocelowy patch: poprawka pl to jedyna zmiana, jaką niesie to wydanie — nie wozi niczego więcej; zawartość review-tail v1.262.2 wyszła osobno.

Tests 6867 → 6868 (+1) · Playwright 176 · rejestr bez zmian: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.262.2] — 2026-10-30

Naprawiono

  • Ogon recenzji falowej — 7 ustaleń o niskiej wadze, każde zamknięte najpierw czerwonym testem. Powrotna podróż backslasha przy imporcie CSV: \ w komórce był zapisywany podwojony i czytany z powrotem podwojony, więc ponowny import tego samego CSV omijał dedup company+role i mógł utworzyć zduplikowany wiersz — czytnik od teraz usuwa escape \\ po podziale (cykl zapis→odczyt jest bezstratny, ponowny import deduplikuje). Wycinanie <head> w cv-voice było kwadratowe przy niedomkniętych tagach — 4827 ms → 13 ms na wejściu 64 KB, którym ogranicza route. statedYearsMin uruchamiał pełny parser lat dla każdej oferty każdego źródła nawet wtedy, gdy years_min nie było skonfigurowane — teraz leniwie, sekundy CPU na duży skan zniknęły. Capture usunięty między readdir a statSync wywalał listowanie posting-guard (TOCTOU — zniknięte pliki są pomijane). Domyślna wartość MiniMax CN pasowała wyłącznie do dokładnie api.minimax.cn — każdy base URL *.minimax.cn dostaje teraz model CN. Tokeny $ Deela, które nie są referencjami hex, nie przeciekają już do snippetu jako literały. Import picker sprawdza file.size PRZED file.text() — limit 512 KB po stronie serwera odpowiadał 413 dopiero po tym, jak przeglądarka sparsowała potencjalnie ogromny plik — z lokalizowanym toastem import.tooLarge ×19.
  • Utwardzenie deploy workflow (recenzja workflows F1–F6). provider było jedynym inputem wstawianym do zdalnego shella bez walidacji zestawu znaków — apostrof ' w wartości wybijał się z cudzysłowów i uruchamiał dowolny kod na prodzie; teraz whitelista ^[A-Za-z0-9_-]+$ przed każdym wstawieniem, a grep strażnika klucza nie da już fałszywego zaliczenia. Krok diagnostyki hermes drukował surowe journalctl + zrzuty unitu do publicznego logu; jego filtr pomijał wielkie litery w *_API_KEY= i niczego nie maskował — teraz wspólne redagowanie niewrażliwe na wielkość liter + maskowanie wartości + ucinanie do 80 znaków na wszystkich trzech ujściach, maskowane są też query strings ?token=. Krok hermes ignorował inputs.app_dir i na sztywno wpisywał /opt/career-ops/src/.env. public_url trafiało do curl bez sprawdzenia https (iniekcja opcji przez wiodący -). A strażnik antydowngrade’owy — poprawka po incydencie v1.238.0 — nie miał wykonywalnej bramki: sześć nowych pinów w ci-workflows (refy bez domyślnych wartości, strażnik odpala się przed Deploy, ścisły regex refów).
  • Ogon import-modal (recenzja SPA). Modal uzbraja ten sam nav guard co modal outcome — przejście na inny widok nie zostawia go już osieroconego na wierzchu innego widoku. Ukryty input pliku jest usuwany przy cancel, nie tylko przy change — powtarzane zamykania nie wyciekają już inputami do document.body. plan.duplicates jest odczytywany przez strzeżoną formę w podglądzie. Alokacja num trackera używa reduce zamiast Math.max(...spread) — spread wpada w limit argumentów przy ~100k wierszy.

Zmieniono

  • Dokumentacja: punkt «118 EN adapters» w przewodniku pomocy nosi teraz licznik także we fr/it/ta (pozostałe 15 locale miało go już wcześniej). Ceny dostawców na cvstart.org zweryfikowane ponownie względem oficjalnych stron cenników — wszystkie cztery bez zmian, CHECKED_ON → 2026-10-30. Przegląd dryfu po wydaniu poprawił 42 nieaktualne linie z licznikami/wersjami w README ×19, CONTEXT.md, CLAUDE.md i podręcznikach SDD (pozostałości ery 109/104 i ery v1.262.0).

Uwagi

  • Świadomie nie zrobiono: natywny window.confirm w cv-studio (era CAR-179) zostaje — konwersja na UI.confirm to follow-up, nie punkt patcha; tooltip <mark title> dla utartych fraz zostaje wyłącznie tooltipem (akceptowalny poziom a11y); remote-qa.yml zachowuje cancel-in-progress: true — ponowny dispatch celowo zastępuje biegnącą regresję.
  • Pełny remote-QA na prodzie v1.262.1: routes ×19 ✓ · site ×19 ✓ · links ✓ · live LLM 18/19 locale A–G ✓ — pl trafił na pojedynczy timeout dostawcy 502 · 300 s · 0 ch (nie teren token-dense; punktowy rerun jedzie z tym wydaniem).
  • Testów 6841 → 6867 na gałęzi wydania (6864 zaliczone / 0 niepowodzeń / 3 pominięte, +26 względem v1.262.1) · Playwright 176 · pokrycie 98.42 % linii / 89.94 % gałęzi · rejestr bez zmian: 123 źródła = 118 EN + 5 RU · 118 adapterów.

[1.262.1] — 2026-10-29

Patch ewaluacji włoskiej: it dołącza do języków token-dense (limit 32768 tokenów + zegar 480 s) po tym, jak era OpenRouter przyłapała go na ucinaniu raportu tuż przed blokiem SCORE_SUMMARY — a narzędzia przełączania dostawcy, które umożliwiły diagnozę, trafiają do deploy workflow.

Naprawiono

  • Ewaluacja it ucięta przed SCORE_SUMMARY (ogon CAR-190): remote-QA 40928864980 (pierwszy przebieg na uzupełnionych kredytach) — ewaluacja it biegła 264 s i wróciła z 15 045 znakami przy tok ~15635 na limicie 16 384: bloki A–G nietknięte, ---SCORE_SUMMARY--- zniknął. Ta sama klasa kształtu, która dała ta jej limit w v1.261.1 (CAR-174). it dołącza do TOKEN_DENSE_EVAL_LOCALES (ta, hi → ta, hi, it): i budżet 32 768 tokenów, i zegar 480 s obowiązują teraz, a /api/evaluate + auto-pipeline pozostają na jednym źródle prawdy w llm.mjs.
  • Raport en bez bloków — jednorazowa wpadka generacji: ten sam przebieg zobaczył pojedynczą ewaluację en, która wróciła poprawna językowo z żadnym z bloków A–G; celowy rerun przeszedł czysto (21 091 znaków, A–G ✓). Nie dodano do zestawu token-dense — jedna wpadka to nie historia.

Dodano

  • Deploy workflow: mode=hermes i mode=provider (ogon ops CAR-190): mode=hermes restartuje bramkę Hermes i drukuje pełną diagnozę (plik unit z wyczyszczonymi sekretami, listenery przed/po, dziennik sudo, sondy per port, własny widok HERMES_BASE_URL aplikacji, saldo kredytów OpenRouter); mode=provider przełącza LLM_PROVIDER ze strażnikiem obecności klucza (odmawia, gdy *_API_KEY dostawcy docelowego go nie ma) i restartuje aplikację — tak prod przeniósł się na openrouter, gdy kredyty Hermes wyczerpały się w locie. Strażnik ref trybu deploy jest walidowany tylko dla mode=deploy, więc dispatche recon/verify znów działają (zmiana wymaganych inputów z ery v1.261.3 uciszyła je).

Uwagi

  • Świadome odstąpienie: en nie trafia do zestawu token-dense — jeden raport bez bloków to wpadka generacji, nie historia objętości.
  • Świadome odstąpienie: wzmocniona dyrektywa językowa ta nie jest rozszerzana na it — nie zaobserwowano dryfu językowego we włoskim.
  • Świadome odstąpienie: nagranie nowej wideo-demo UI-v2 zostaje przy właścicielu (CAR-141) — landing i tak osadza teraz przez youtube-nocookie.com.
  • Testów 6841 → 6841 na gałęzi wydania.

[1.262.0] — 2026-10-29

Minor z funkcjami z upstreamu: tablica Deel dołącza do skanera (rejestr 123), CSV z innego trackera importuje się prosto do #/tracker, check integralności posting-guard i check głosu CV trafiają jako relay/lint, skaner uczy się filtru lat doświadczenia, a przyciski Apply w siedmiu kolejnych językach przestają wyglądać na brakujące — do tego zastąpiony wycofany model domyślny MiniMax i reposty już nie fabrykowane między źródłami.

Dodano

  • Źródło tablicy Deel (CAR-184): rejestr 123 źródła = 118 EN + 5 RU · 118 adapterów — automatycznie wykrywa tablice tenantów jobs.deel.com/<slug> (Klarna i inni); payload flight Next.js niesie cały katalog w jednym żądaniu (tytuły, lokalizacje, forma pracy, daty, opis), niedozwolona ścieżka /api/ nie jest nigdy dotykana, tenant serwujący karierę gdzie indziej odpowiada przekierowaniem, które źródło odrzuca z nazwy, a wynagrodzenie celowo nie jest mapowane (kwoty bez interwału płatności byłyby zgadywaniem); bramki liczników ×5 + pomoc §17 ×19.
  • Import CSV trackera (CAR-181): POST /api/tracker/import-csv z podglądem dry-run i zablokowanym commitem — cudzysłowy RFC-4180, daty w formach ISO / dzień-na-początku / nazwa-miesiąca, etapy obcego trackera składane przez kanoniczne stany (nieznany etap ląduje jako Evaluated z notatką, nigdy nie wyrzucony), dedup po znormalizowanym URL-u ogłoszenia czytanym z komórki linku markdown albo kolumny Notes, limity 512 KB / 2000 wierszy; #/tracker dostaje przycisk Import CSV z modalem podglądu, i18n ×19.
  • Relay posting guard (CAR-182): POST /api/runners/posting-guard — deterministyczna, zero-LLM bramka integralności JD z rodzica, rozwiązywana numerem raportu przez regułę prefiksu przechwyceń jds/ (z wypełnieniem lub bez, porównywana jako liczba) albo jawną zsanityzowaną ścieżką; dziecko dostaje tylko argv, sufit 30 s i kontrakt fail-soft; akcja «Posting guard» na #/reports/:slug renderuje ustalenia, i18n ×19.
  • Check głosu CV (CAR-188): 27 utartych fraz z CV (passionate about, proven track record, leveraged, spearheaded, delve…) plus heurystyki myślnikowe (przedział lat jak 2022–2024 to nie wskazówka; 20–30% już tak) jako read-only POST /api/cv-studio/voice-check i karta #/cv-studio, która podświetla dokładne trafienia; lista Tailor rośnie do sześciu niezmienników; i18n ×19.
  • Filtr skanu po latach doświadczenia (CAR-180): parser jd-years (65 sformułowań, w razie wątpliwości nigdy nie porzuca) czyta zadeklarowane minimum z opisów ogłoszeń, nowa opcja years_min: w portals pomija ogłoszenia poniżej kwalifikacji jako skipped_experience (obserwacyjny status historii, który nigdy nie przypina URL-a), a yearsMin jedzie w snapshocie skanu na przyszły UI.
  • Kontrolki Apply w siedmiu kolejnych językach (CAR-185/189): wietnamski Nộp đơn ứng tuyển, bułgarski Кандидатствай/Кандидатстване/Външно кандидатстване (rzeczownik zakotwiczony na początku etykiety — linki do artykułów poradnikowych to nie Apply), niderlandzki Solliciteer/Solliciteren, hiszpański ¡Apúntame!/Postularse (etykiety, nie czasownik — linki FAQ przestają przeszkadzać), chiński 申请职位/投递 (zakotwiczony na całej kontrolce) — żywe ogłoszenia na tych tablicach przestają czytać się jako no_apply_control.

Naprawiono

  • Model domyślny MiniMax (CAR-187): wycofany domyślny MiniMax-Text-01 zastąpiony przez MiniMax-M3.1-Flash na api.minimax.io i MiniMax-M3 na api.minimax.cn; bazowy URL przypięty do dostawcy (host spoza dostawcy odrzucany w runtime, a klucz nigdy tam nie dociera); podpowiedź w ustawieniach ×19 wymienia nowe domyślne.
  • Reposty wymagają tego samego źródła (CAR-186): rola wystawiona na LinkedIn i na Greenhouse pracodawcy nie jest już zgłaszana jako repost — klastry dzielą się teraz po sourceHost(), który skleja regionalne subdomeny tylko na znanych serwisach (de.linkedin.com ≡ www.linkedin.com, ale ca.example.com zostaje osobno), skleja aliasy hostów Greenhouse w jedno źródło i obcina końcową kropkę.
  • Dryf języka ewaluacji tamilskich (CAR-183): wzmocniona dyrektywa tamilska siedzi teraz w zmiennym ogonie prompta obok budżetu objętości (slot CAR-174) — raporty remote-QA znów lądują po tamilsku po okresowym dryfie z v1.261.2.

Uwagi

  • Świadome odstąpienie: relay posting-guard wyjeżdża fail-soft — fork nie niesie jeszcze posting-guard.mjs rodzica (upstreamowy PR #6146 wciąż otwarty), więc endpoint odpowiada {available:false, reason:"script-not-found"}, dopóki synchronizacja z rodzicem go nie dostarczy.
  • Świadome odstąpienie: yearsMin nie występuje jako chip UI #/scan w tym wydaniu — pole jedzie w snapshocie, a filtr jest wyłącznie w konfiguracji portals.
  • Świadome odstąpienie: zmiany Machine Summary w upstreamowym modes/reports (#6161/#6160/#6157) nie są portowane — przyjdą z wdrożonym rodzicem, nie jako lustra web-ui.
  • Testów 6734 → 6841 na gałęzi wydania; klucz dedup skanera nietknięty (zachowanie normalizacji URL nie zmieniło się).

[1.261.3] — 2026-10-28

Łatka domknięcia designu: faza 3 designu Lovable (gęstość + pełne wycofanie koralu), pula hostów skanu (32 firmy, 10 na host), sześć poprawek lokalizacji dostawców z upstreamu, źródło Trakstar Hire (rejestr 122), undo + straż niezapisanych zmian w CV Studio — plus poprawki finalnej regresji P3 i parzystość dokumentacji.

Naprawiono

  • Etykieta «related» klastra mapy 3.16:1 → 4.68:1 (oba motywy): jasny --map-score-mid przyciemniony do #567b75 (proponowany #5f7f7a mierzył tylko 4.37 — potrzebny był o krok ciemniejszy); strona ciemna miała już 4.98:1, nietknięta. Przypięcie testem najpierw czerwonym w map-cluster-visual.
  • Pierścień fokusu skip-linka: ostatni literalny obrys #ff385c → var(--accent-c) — wszystkie 78 pierścieni fokusu podąża teraz za tokenem akcentu.
  • Topologia akcentu .tab-btn.is-active (#584, faza 3): kontrolka mieszała trzy rodziny kolorów (koralowa poświata + tekst danger + niebieska ramka); teraz jedna para accent-soft.
  • Poprawki lokalizacji dostawców z upstreamu ×5 (#580, CAR-176): workday — flaga Fully Remote (to nie miejsce), workable — rozdmuchanie telecommuting + stan tylko gdy brak miasta, successfactors — końcowy przecinek, lever — granica słowa dla remote, icims — etykiety z prefiksem Location.
  • http-json: brak retry po wyczerpanym timeoutie (#580) — abort po deadlinie nie jest przejściowy w obu helperach retry (upstream zmierzył ~94 s na jednej tablicy Ashby przy 30 s × retry).
  • Parzystość dokumentacji (#587): ostatnie liczniki z epoki 17/18 w HANDOFF/CONVENTIONS/README (uk dostał brakującą sekcję Локалізація; historia § rozszerzona do §32/§33 — arytmetyka 33 H2 zweryfikowana).

Dodano

  • Faza 3 designu Lovable (#584): tokeny gęstości żyją — wiersze tabel ≈32px, kontrolki 30px, chipy 24px (wyjątek odstępów WCAG 2.5.8); każda pozostałość koralowego rgba przeniesiona na pary cv3 (.dash-hero, .badge-bad, poświaty, .tab-btn.is-active); zadeklarowane --ease-out, TOKEN_HANDOFF puste; kontrakt .callout--ok/--danger.
  • Źródło Trakstar Hire (#583, CAR-177): rejestr 122 źródła = 117 EN + 5 RU · 117 adapterów — host-pinned jsapi.recruiterbox.com, przejście offsetowe ze stopami short/empty/repeated, wyniki częściowe zachowane, tagowanie trakstarTruncated; bramki liczników ×5 + pomoc §17 ×19.
  • Pula hostów skanu (#579, CAR-178): do 32 firm równolegle, limit 10 na host (wzorzec keyed-limiter z upstreamu) — snapshot bajt w bajt identyczny z przebiegiem sekwencyjnym (bramka czasowa na makiecie, najpierw czerwona).
  • Undo + straż niezapisanych zmian w CV Studio (#582, CAR-179): ograniczony stos undo (30) nad wynikami przebiegów AI z Cmd/Ctrl+Z bezpiecznym na nie-QWERTY, straż niezapisanych zmian przy opuszczaniu trasy (dirty sondowany na żywo, confirm/rewind/beforeunload), i18n ×19.
  • Poprawki dostawców z upstreamu przetestowane ×17 (część CAR-176); podsumowanie remote-QA wymienia zawodzące źródła skanu + tok ~N na ewaluację (#567, już w v1.261.2 — obserwowalność użyta do triage tego wydania).

Uwagi

  • Akcent jest teraz niebieski (koncept Lovable): akcje podstawowe/stany aktywne/pierścienie fokusu podążają za --cv3-accent; czerwony zarezerwowany dla danger (.btn-danger, toast.error, tekst danger). Koral przetrwał tylko w zasobie logo PNG (decyzja właściciela).
  • Gęstość: wiersze tabel ≈32px / kontrolki 30px / chipy 24px — wyjątek odstępów WCAG 2.5.8 udokumentowany; kanarek 44px z v1.26.1 przepisany na kontrakt tokenów.
  • CodeQL: wszystkie 10 otwartych alertów zamknięte (4 odrzucone jako FP z uzasadnieniem: udokumentowane klasy llmRateLimit/atomicWrite; 6 naprawionych u źródła).
  • Testów 6655 → 6734 na gałęzi wydania; zachowanie źródeł skanera nie zmieniło się poza nowe źródło Trakstar.

[1.261.2] — 2026-10-28

Łatka stabilności + szlifu: cache geokodera przeżywa awarię w połowie zapisu (CAR-173), UI.md renderuje kontynuacje punktów list i zagnieżdżone listy, przecieki kluczy w wyrenderowanym tekście pakietów pomocy zamknięte ×17, ewaluacja zyskuje limit tokenów dla ta (CAR-174), chrom interfejsu w RTL odbija się lustrzanie dzięki właściwościom logicznym (85 ustaleń), zrzuty mapy kadrowane są od nowa ×19, a klastry mapy przechodzą kontrast w ciemnym motywie — plus pierwsza faza integracji designu Lovable (pasywny arkusz tokens-v3.css), dogranie zaległości dokumentacyjnych (przegląd wydania + specyfikacje) i wyłączenia pokrycia dla wariancji node w CI.

Naprawiono

  • Utrata cache geokodera przez poszarpany zapis (CAR-173, #562): obie ścieżki zrzutu (zrzut wstawek z debounce’em, zrzut przy wyjściu) zapisywały .cache/geocode.json gołym writeFileSync — najpierw truncate, potem zapis — więc awaria, OOM albo SIGKILL w połowie zapisu zostawiała poszarpany plik, a JSON.parse przy kolejnym starcie rzucał, po cichu wyrzucając cały trwały cache (tygodnie budżetu Nominatim), nie tylko bieżący dzień. Oba miejsca zapisu przechodzą teraz przez file-lock.mjs::atomicWrite (plik tymczasowy w tym samym katalogu → rename → unlink przy porażce) — ten sam kontrakt, który FULL-R1/FULL-M1 nałożyły na pipeline.md, cv.md, profile.yml, career-plan, wejście batcha i pamięć. Sama maszyna zrzutu z CAR-142 (zrzut wstawek z debounce’em, zrzut przy wyjściu, ograniczone zamykanie) została zweryfikowana jako nienaruszona — testy najpierw czerwone: (a)/(b) blokują, że wstawki docierają do pliku w oknie GEOCODE_SAVE_MS i że plik pozostaje poprawnym JSON-em; (c) to bramka mechanizmu plus behawioralne przebiegi obu ścieżek zrzutu, sprawdzające brak tymczasowych śmieci i parsowalność pliku.
  • Kontynuacja listy w UI.md (#563): handler list konsumował wyłącznie kolejne linie - /* , więc wcięta linia kontynuacji po punkcie wypadała z emitowanego <ul>, a przebieg akapitowy pomijał ten fragment — kontynuacja przeciekała jako surowa proza z literalnymi markerami **/backticków (~95 wiszących fragmentów prozy na locale w pakietach pomocy; en.md 95, ru.md 104). Linia kontynuacji — wiodący whitespace, nie nowy blok (nagłówek, punkt, NUL-otoczony placeholder fences, pusta linia) — dołącza teraz do poprzedniego <li> jako tekst sklejany przez <br/>, z inline() uruchamianym per linia, żeby markery emfazy nigdy nie parowały przez sklejenie; strażnik placeholderów fences sprawdza NUL jako pierwszy znak, a nie gołe dopasowanie tokenu. Zagnieżdżone punkty -, listy numerowane, fences wewnątrz list i nagłówki wewnątrz list pozostają udokumentowaną, osobną luką (następna fala dokumentacyjna).
  • Przecieki kluczy w wyrenderowanym tekście pomocy ×17 (#561): remote-QA znalazła 85 surowych kluczy i18n widocznych w wyrenderowanej pomocy (przyczyna źródłowa udowodniona przez repro: to samo konsumowanie jedno-liniowych punktów przez UI.md — zawinięta kontynuacja emitowana jako surowy tekst trzymała backticki literalnie; sekcje pomocy v1.260/261 pisały wieloliniowe punkty). 163 punkty rozłożone do jednej linii w 17 locale — zmiana wyłącznie w whitespace, nie dotknięte ani jedno przetłumaczone słowo (zweryfikowane stary-vs-nowy). Nowa bramka tests/help-rendered-keys.test.mjs renderuje każdy pakiet przez prawdziwy łańcuch (stripGithubOnlyBlocks + UI.md ładowane w vm) i zawodzi, gdy którykolwiek z 1 711 kluczy pojawi się w tekście; najpierw czerwone w 17 locale → zielone. Narzędzia repro trafiają do repo: scripts/remote-qa/help-render-scan.mjs (vm) + help-render-crosscheck.mjs (prawdziwy DOM).
  • Remote-QA Ctrl+K weryfikuje kontrakt palety CAR-122 (#561): prod-regression.mjs oczekuje teraz palety komend po Ctrl+K (.nav-v2-palette[role=dialog] + fokus w nav-v2-input) LUB legacy fokusu wyszukiwania jako fallbacku, zamiast po cichu akceptować cokolwiek; test jednostkowy tests/remote-qa-ctrl-k.test.mjs blokuje 6 scenariuszy na mocku DOM, najpierw czerwone 0/6 → 6/6.
  • Kadrowanie zrzutów mapy ×19 (#560): zgłoszenie właściciela na images/job-map-en.png — połowa wyszukiwania topbara + ucięty h1 na górze, szary pasek listy bocznej przy prawej krawędzi, klaster markerów ucięty ramką niedaleko Londynu i biała pozioma linia przez mapę na ~2/3 wysokości. capture-map-screenshots.mjs czeka teraz na opróżnienie kolejki geokodowania (located + noLoc === total, nie licznik N/N — wiersze Remote strukturalnie nie mają lokalizacji, więc stare czekanie nigdy nie mogło się dopełnić), chowa header.topbar i #notif-drawer na czas zrzutu, przycina dokładnie do ramki .job-map-page (żaden panel nie jest ucięty krawędzią kadru), oddala o dwa kroki, żeby żaden klaster nie wisiał przecięty na pół, przypina wysokość mapy i bierze zwykły zrzut viewportu (captureBeyondViewport przesamplowuje złożoną warstwę kafelków i maluje białe pasy na granicach rzędów kafelków) oraz wyrównuje kontener mapy do wartości całkowitych. Wszystkie 19 zrzutów job-map wykonanych od nowa.
  • Bąble klastrów mapy — kontrast w ciemnym motywie + dopasowanie etykiety (#572): przegląd właściciela P2/P3 — pierścienie klastrów w ciemnym motywie siedziały na stałym białym wypełnieniu (1.83:1); pierścienie biorą teraz var(--paper) z cyframi z palety wyniku (zmierzone 4.98:1+, wypełnione 9.53:1; najniższy pas jest matematycznie niekolorowalny na ciemnym i trzyma 6.1:1 przez uczciwą ścieżkę data-dim), a etykieta related mieści się w swoim bąblu (dopasowanie fontu przez rAF, liczby nigdy się nie kurczą).
  • #/scan po zmianie języka — ponowne uzbrojenie szkieletów (dokładka do #534, agent w locie, ląduje przed tagiem): kontynuacja poprawki właściciela z v1.261.0 (#534) — ponownie uzbrojone szkielety przy przemalowaniu po zmianie języka nie przeżywają już dokończonego ponownego pobrania danych.
  • Dryf dokumentacji (CAR-139, agent w locie, ląduje przed tagiem): liczniki README ×19, HANDOFF ×19, fakty w CONVENTIONS zresynchronizowane z żywym rejestrem i stanem testów.

Dodano

  • Przegląd wydania + dogranie specyfikacji (dokumentacja, #559/#558): docs/reviews/REVIEW-2026-10-28-v1.261.1.md (fala v1.261.0/v1.261.1 przejrzana względem swoich specyfikacji) i uzupełnienie specyfikacji SDD dla tej samej fali — ogon BACKLOG-u wskazuje teraz pozostałą lukę (dedykowane testy dla sources/habr.mjs).
  • Pogłębiony przegląd RTL (#571): harness AR przechodzi przez 39 tras × LTR-vs-RTL (lustrzane X, przepełnienie, przycinanie, sygnatury text-align) — 85 ustaleń naprawionych: stały chrom (toast, sidebar, szuflada z jej krzyżykiem zamykania, docs-FAB, usage-HUD, skip-link) przeniesiony na inset-inline-*/border-inline-*, tabele na text-align: start/end w 17 plikach widoków + 2 bibliotekach, kocowa reguła [dir=rtl] text-align:right usunięta (walczyła z centrowaniem kolumny gwiazdek skanu), a izolacja kolumny wyniku z CAR-58 przeniesiona na span ltrNum.
  • Harness dostępności klawiatury (#570): tests/playwright-a11y-keyboard.mjs przechodzi przez 11 tras (kolejność i pułapki Tab, wskaźniki fokusu, nakładki po Escape, Enter/Spacja) — 0 defektów produkcyjnych; pokrycie regresyjne jest nowe.
  • Przegląd nieprzetłumaczonych ciągów i18n (#565): 36 wartości identycznych z en przetłumaczonych ×9 locale (*.rolePh, klucze config, manifest ta) + strażnik przeglądu z zamkniętą białą listą; audyt i18n serwisu (cvstart.org) (#568): 20 kluczy × 18 locale przetłumaczonych (cały blok demo.*/stats.t.*/showcase.tab* był po angielsku wszędzie), 1 martwy klucz usunięty ×19.
  • Obserwowalność remote-QA (CAR-175, #567): podsumowanie wymienia zawodzące źródła skanu (próbki stderr, redagowanie przed skróceniem) i wypisuje tok ~N z użycia dostawcy; logika żyje w czystym summary-parts.mjs z bramką dryfu.
  • Zagnieżdżone listy z markerami w UI.md (jeden poziom, #564): punkty - renderują się jako zagnieżdżony <ul> (bezpiecznie względem placeholderów fences) — ostatnie 2 wiszące fragmenty prozy na locale zniknęły.
  • Integracja designu Lovable — faza 1 (#566) / faza 2 (gałąź, ląduje przed tagiem): public/css/tokens-v3.css przenosi koncepcję Lovable słowo w słowo (powierzchnie oklch 0–3, pary ink z adnotacjami AA, rodzina akcentów, soft+ink dla ok/warn/danger/info/neutral, pasy wyniku A–G ×2 motywy, gęstość + fokus + cienie); faza 2 aktywuje go na istniejących nazwach tokenów (akcent rozdzielony na blue/danger, pasy wyniku + callouty na tokenach cv3) ze zaktualizowanymi bramkami kontrastu/roli/motywu ciemnego.
  • Limit tokenów ewaluacji per locale (CAR-174, #569): evalMaxTokens(lang) — ta/hi proszą o 32768 (trzej klienci SDK doklampowywali do 16384; naprawione obie warstwy), plus budżet objętości tamilskiego w prompcie (≤5 zdań na blok, ≤900 słów) — raport ta z remote-QA w v1.261.1 został ucięty na limicie tokenów wyjścia (brakowało bloków B–G + SCORE_SUMMARY).
  • Dowiązanie do prawdziwych poprawek CodeQL: nowe narzędzia renderu QA zastąpiły ręcznie zwijaną obsługę encji strukturalnymi przebiegami podziału + htmlToText({cap: Infinity}); asercje redagowania przypinają dokładne zamaskowane wyjście; nieużywane stałe harnessu RTL usunięte.
  • Polityka wyłączeń pokrycia dla wariancji node w CI (habr #558, states #561): sources/habr.mjs (pokrycie gałęzi w macierzy node CI 87.23 wobec lokalnych ≥89) i states.mjs (CI 86.49 wobec lokalnych ≥89) dołączają do wyłączeń w scripts/coverage-baseline.json — pliki, których zmierzone pokrycie gałęzi w CI jest strukturalnie poniżej lokalnego progu z powodu wariancji wersji node, są wyłączane, zamiast obniżania progu całej bramki.

Uwagi

  • Kontrakt Ctrl+K (CAR-122): akord otwiera paletę komend — NIE fokusuje bezpośrednio pola wyszukiwania; wyszukiwanie dostaje fokus z palety. Regresja prod remote-QA weryfikuje teraz dokładnie to (#561).
  • Odrzucenia fałszywych alarmów CodeQL ×5: alerty js/missing-rate-limiting na main czekają na token security_events — akcja operatora, nie zmiana w kodzie.
  • Wylądowało po odcięciu gałęzi: #561/#562/#563/#564/#565/#566/#567/#569/#570/#571/#572 są scalone do main; agenci #534-szkielety i CAR-139 scalają się przed tagiem. Zagnieżdżone listy powyżej jednego poziomu i geometria widoków bogata w inline pozostają udokumentowanymi lukami.
  • Testów 6609 na gałęzi wydania (+15 od v1.261.1; ~13 więcej z #561 przy scaleniu — 2 nowe pliki bramek); jedynymi czerwonymi testami przed fan-outem są bramki parzystości CHANGELOG ×19 (fan-out locale to kolejny krok orkiestratora); żadne źródła skanera nietknięte (rejestr 121 = 116 EN + 5 RU · 116 adapterów).

[1.261.1] — 2026-10-28

Łatka kliencka z prod-QA: poprawka awarii P1 w #/two-pager, Ctrl+K działający na układach nie-QWERTY, fala mobilna 390px (przepełnienie docs-assistant, nachodzące chipy mapy, harness 39 tras), domknięcie CAR-137 (konkretne błędy, v2empty ×5, podpowiedzi ×13 + strony trybów) i CAR-140 — prawdziwe zrzuty v2 wszędzie.

Naprawiono

  • TDZ w two-pager (CAR-170, P1, #554): Cannot access 'previewTimer' before initialization — edytor zapisanych tagów odpalał onChange w trakcie konstrukcji dla każdego przywracanego chipa, podczas gdy pętla konstrukcyjna leksykalnie siedziała nad let previewTimer, więc cały render #/two-pager się wywalał (bez h1, ×19 locale). Scheduler + bindowanie żyją teraz nad pętlą; test behawioralny wykonuje prawdziwy moduł widoku — dokładny błąd produkcyjny przed poprawką, wyrenderowana strona po niej — plus bramka dryfu porządku leksykalnego.
  • Ctrl+K na układach nie-QWERTY (CAR-172, #554): oba handlery akordów dopasowywały wyłącznie e.key — na rosyjskim układzie akord przychodzi jako key='л' code='KeyK' i nic nie robił. Dopasowanie po e.code === 'KeyK' w nav-v2.js i app.js; odtworzone w prawdziwej przeglądarce syntetycznym akordem ‘л’/KeyK. Kontrakt CAR-122 powtórzony wprost (patrz Uwagi).
  • Przepełnienie docs-assistant przy 390px (CAR-172, #554): startowe chipy CAR-136 były .btn (nowrap, flex-shrink: 0) — jeden niełamliwy element 418px wypychał #/docs-assistant 56px poza viewport 390px; wzorzec kurczenia CAR-146 (w v2-llm.css, bramki CSS 800-LOC nietknięte) sprowadza to do 0.
  • Nachodzące chipy mapy @390 (#552): na viewport 390px meta-chipy mapy nachodziły na rząd CTA (map.css).
  • CAR-137 — konkretne błędy + v2empty ×5 (#550): pięć generycznych fallbacków błędów (‘Error’ / ‘failed’) stało się konkretnymi kluczami, które mówią, co dalej — porażka POST ewaluacji, strumień auto-pipeline bez zdarzenia terminalnego, dodawanie scan→pipeline, ładowanie klastrów repostów, undo pipeline; ostatnie pięć płaskich pustych stanów (#/reports, #/usage, #/portals, #/activity, #/dashboard) dołącza do wzorca CAR-124 v2empty (wyjaśnienie + oznaczony aria-hidden przykład + podpięta z góry akcja; 15 nowych kluczy v2empty.*, cztery martwe jednolinijkowe klucze usunięte) — wszystko ×19 słowników, snapshot wygenerowany ponownie.
  • CAR-137 — HelpHint ×13 + zestaw stron trybów (#550): kontekstowa podpowiedź «?» siedzi teraz na każdym pozostałym H1 strony (pipeline, reports, dashboard, cv, portals, usage, activity, assessments, map, health, docs-assistant, settings) i na 8 stronach trybów przez zestaw (każda konfiguracja MODES niesie hintKey, renderowany przez HelpHint.title).

Dodano

  • Harness mobilny 390 (#552): przebieg Playwright po każdej trasie SPA (31 kanonicznych + 8 stron trybów = 39 hashów) przy 390×844 z zaseedowanym korpusem — kontrola poziomego przepełnienia per trasa (scrollWidth vs clientWidth, tolerancja 1px, nazywa najszerszego winowajcę) plus kontrola trafień CTA (żaden sticky pasek/szuflada/FAB nie zakrywa głównego CTA); opt-in, eleganckie pominięcie bez binarki przeglądarki, bez sieci.
  • Świeże zrzuty v2 ×48 (CAR-140 faza A, #551): prawdziwe zrzuty ekranu UI v2 z zaseedowanego, od CI odizolowanego fixture — dashboard ×19 + job-map ×19 (job-map-ta debiutuje, job-map-vi nowe) + scan/pipeline/tracker/reports × en/ru — zasilają README, pomoc i landing.
  • Prawdziwe zrzuty na cvstart.org (CAR-140 faza B, #553): sloty-zagłuszki CAR-140 zniknęły — landing pokazuje rzeczywiste zrzuty v2 (showcase job-map + rzędy ze zrzutami ekranu, ×19 locale landingu).
  • Podpowiedzi CAR-137 (#550): 21 nowych przetłumaczonych kluczy ×19 (help.hint.* ×20 + hintKey-i stron trybów) — każda strona teraz tłumaczy się sama na miejscu.

Uwagi

  • Kontrakt Ctrl+K (CAR-122): akord otwiera paletę komend — NIE fokusuje bezpośrednio pola wyszukiwania; wyszukiwanie dostaje fokus z palety. Linia checklisty QA v1.261.0 «Ctrl+K фокусит поиск» zostaje zastąpiona; prompt QA v1.261.1 niesie zaktualizowaną kontrolę.
  • Prawdziwe poprawki CodeQL (#547): 4 alerty zamknięte (iteracja po kluczach-literalach w content.mjs uporządkowana strukturalnie, sprzątanie linta) — wylądowały po wydaniu na main v1.261.0 przed tą łatką; wymienione tu dla kompletności.
  • Testy 6582 (+51); zestaw przeglądarkowy 171–172 zaliczone / 0 niepowodzeń / 1 opcjonalnie pominięty; harness mobilny 390 działa samodzielnie (node tests/playwright-mobile-390.mjs). Żadne źródło skanera nietknięte (rejestr 121 = 116 EN + 5 RU · 116 adapterów).

[1.261.0] — 2026-10-28

Pociąg pełnego przeglądu zakończony (wszystkie ustalenia HIGH + MEDIUM wylądowały w v1.261.0), poprawka przełączania języka zgłoszona przez właściciela, poprawki jakości ewaluacji, fan-out pomocy ×18, landing cvstart.org v2 — plus 4 specyfikacje SDD/OpenSpec dokumentujące pociąg. Każda poprawka przeszła red→green fix-forward oraz recenzję GLM-5.3-Flash w świeżym kontekście.

Bezpieczeństwo

  • FULL-R1 — bramka CSRF na acting-GET + zablokowane atomowe zapisy pipeline’u (#519): bramka Sec-Fetch-Site/Origin/Referer na /api/stream/*, /api/run/*, /api/geocode (wyeksportowane ACTING_GET, statyczna bramka pokrycia); każde odczytaj–modyfikuj–zapisz dla data/pipeline.md / data/last-scan.json pod withFileLock + nowe atomicWrite (plik tymczasowy w tym samym katalogu → rename → unlink przy porażce).
  • FULL-R2 — klaster SSRF w źródłach (#514): rss.mjs — https + odrzucanie adresów prywatnych; ~25 źródeł na gołym fetchImpl → strzeżone transporty; mirrory przypięte; walidacja przekierowań dla habr/hh/geekjob/getmatch; współdzielone delay(ms, signal).
  • FULL-R4 — uszkadzanie prozy w stripDangerousMarkdown (#513/#518): wycinanie schematów tylko w kontekstach linków/atrybutów; encje dekodowane do kopii używanej wyłącznie do wykrywania („JavaScript: React, Node” i „R&D” przeżywają).
  • FULL-M2 — utwardzenie transportu (#520): safeGet honoruje timeoutMs razem z sygnałem wywołującego (bridge controller); guardResolvedHost przy błędzie DNS zawodzi fail-closed. #525 dodaje zrzucanie nagłówków poświadczeń przy przekierowaniach cross-origin, odczepianie transportowego słuchacza na każdej ścieżce domknięcia oraz poprawkę awarii przy sygnale przerwanym z wyprzedzeniem.
  • FULL-M4 — logo/batch (#523): logo przypina magic bytes na KAŻDEJ ścieżce (kłamliwy image/png nie uniesie SVG), content-type zawężany do image/* w chwili zapisu, prywatny cache + nosniff; batch: --parallel zawężone do 1–8, --min-score walidowane, BATCH_BUSY single-flight, llmRateLimit na mutacjach config/batch.

Dodano

  • CAR-147 — limit ewaluacji świadomy języka (#524): evalTimeoutMs(lang) — ta/hi dostają 480 s zamiast 300 s (skrypty indyjskie tokenizują kilka tokenów na sylabę; stara ściana dawała 502 + pusty raport); klient remote-QA czeka 540 s.
  • CAR-133 — landing cvstart.org v2 (#532): paralaktyczny hero za bramką reduced-motion, wyraźnie opisane SYMULOWANE demo przepływu scan→evaluate→tracker, sekcje scroll-reveal z liczbami zweryfikowanymi na żywo, sloty-zagłuszki pod zrzuty ekranu CAR-140.
  • CAR-135 — pomoc przepisana pod UI v2, fan-out ×18 ukończony (#533, #540, #541, #542): wszystkie 19 plików pomocy opisuje powłokę v2 (zwijana nawigacja, paleta Cmd/Ctrl+K, szkielety, puste stany example+action, chrome skanu v2, pipeline z grupowaniem i undo, raporty v2, kanban); etykiety interfejsu cytują swoje klucze i18n; zdanie o 121 źródłach żyje z rejestru.
  • Specyfikacje (SDD/OpenSpec) (#535): backfill fali drugiej za oct27 + trzy specyfikacje naprzód, dokumentujące falę v1.261.0 (fan-out pomocy, przekazania zapisów, niezmienniki przełączania języka).

Naprawiono

  • Przełącznik języka nie wyczerpuje już #/scan (#534) — zgłoszone przez właściciela: stan skanu lokalny dla widoku (wyniki, chipy fasetów) żyje teraz na poziomie modułu; behawioralny harness Playwright z opóźnionym o 4 s refetchem (red na starym kształcie).
  • CAR-148/149 — raporty ru „missing Block G” (#530): prompt uczył trzech niespójnych map A–G; szkielet + lista + przykład są teraz zgodne z oferta.md (G = Posting Legitimacy); behawioralna bramka dryfu.
  • CAR-150 — undo w pipeline zachowuje metadane comp (#537): DELETE odpowiada comp, POST przyjmuje bramkowane opcjonalne comp, widok przenosi {token, comp} przez wszystkie gałęzie fallback.
  • FULL-M3 — martwe źródła raportują uczciwe tablice (#522): getro/mycareersfuture/meituan/mokahr/glints rzucają przy zniekształconej stronie 1 (martwe API nie czyta się już jako „healthy, 0 jobs”); pinnedOverride przypina nadpisania company.api w 18 adapterach.
  • FULL-M5 — jedna kaskada dostawców (#521): routes/llm.mjs przez runActiveProvider (+cachePrefix, sygnał); przechwyt podprocesu Gemini; kontrakty odpowiedzi bajt w bajt identyczne.
  • FULL-M1 — zapisy współdzielonych plików pod blokadą (#526, #539): runTrackedScript + roster TRACKER_MUTATING; wywołania outcome/followup trzymają blokadę; tracker.mjs zapisuje przez atomicWrite; zapisy PUT locked+atomic.
  • FULL-M6 — konsolidacja serwera i klienta (#531, #536, #525): dotenv z prototypem null + odmowa __proto__; isPrivateOrLoopback rozpoznaje NAT64/6to4/benchmark/reserved; cache mtime w env-config; prawdziwe GC slotów w file-lock; safeGet timeout+sygnał; strażnik DNS fail-closed; SSE ×4 → API.postStream; biblioteki fokusu/etykiet/statusów; clipboard z await; podbarwienie Hired na dashboardzie.
  • R3 — dryf tokenów CSS (#527): --accent rozwiązany (pierścienie fokusu mapy były po cichu martwe); 11 czasów trwania poza tokenami zwinniętych; bramka dryfu.
  • R4 — zaległości stanów ładowania (#538): podgląd assessments/mode-page/pipeline renderuje szkielety CAR-112.
  • Partia CodeQL + CI (#517, poprawka w #539): nieużywane importy, bramka ACTING_GET importuje prawdziwe wyrażenie regularne, wycinek lifecycle zakotwiczony na nowo.

Uwagi

  • Świadomie nie zrobiono: przypinanie DNS w chwili połączenia (wymaga undici — poza zależnościami; pozostałość udokumentowana); zrzuty ekranu CAR-140 (wymagają wdrożonego UI v2); CAR-137/138/141 (następna tura dokumentacji); klasa CodeQL js/missing-rate-limiting to udokumentowany fałszywy pozytyw (własny limiter nie jest kredytowany).
  • Fan-out pomocy ×18: es/de w fali 1 pominęły notkę wprowadzającą i deltę karty Active Companies (de wylądowało własne wprowadzenie; es dostaje follow-up o jednej linii).

[1.260.0] — 2026-10-26

Pociąg utwardzania po recenzjach — osiem scalonych PR-ów (#491–#498) z rund opus-5-5 i recenzji AI nad flotą v1.259.0: normalizacja wynagrodzeń, zakres korekty dat raportów, odporność geokodowania, cache-busting pakietu r2+r3, poprawka przepełnienia deep — plus dwa interfejsy v2 (pipeline, raporty). Każda poprawka wylądowała na drodze czerwony→zielony fix-forward.

Naprawiono

  • Normalizacja porównywania wynagrodzeń (CAR-143 rev-2): znaczniki okresu są rozpoznawane tylko w pobliżu liczby, do której należą — „6 month contract, $120k” nie jest już annualizowana ×12, a formy okresu występujące wyłącznie w RU/ES („за месяц” tuż przy liczbie) wygrywają z przypadkowymi słowami; rodzina symboli $/¥ jest rozpoznawana, lecz nie odwzorowana na walutę, chyba że ten sam wiersz zawiera jawny kod ISO (dolary AUD/CA/SG nie są już rozliczane jako USD, a kształt ¥ RMB dostaje jawne zastrzeżenie zamiast konwersji na JPY mijającej się ~20×); gołe liczby 19xx/20xx to zawsze lata; liczby zakresu dziedziczą okres partnera; minimum i target_range z profilu nigdy nie są sklejane w jeden zakres.
  • Zakres działania fixReportDate (CAR-144 rev-2): korekta daty przypinanej po stronie serwera dotyczy wyłącznie preambuły przed pierwszym nagłówkiem ## (raport z tytułem H2 dostaje zachowawczy no-op — przestarzała data jest akceptowalna, zmyślona już nie); wewnątrz preambuły: unikalny kandydat zostaje skorygowany, w przeciwnym razie unikalny pogrubiony **Date:**, w przeciwnym razie nic (dwa pogrubione lub dwa zwykłe kandydatów nie przepisują żadnego). Bramka etykiet PDF FIX-5 czyta teraz rzeczywiście złożony słownik — brakująca wersja językowa rzuca wyjątek zamiast po cichu przechodzić na angielski fallback.
  • Chip lokalizacji Habr + odporność geokodowania (CAR-142 rev-2): meta-chip Habr staje się miastem wyłącznie przy dowodzie strukturalnym (link filtra miasta lub ikona lokalizacji) — ogłoszenia o relokacji („Возможна релокация”) i typy zatrudnienia nigdy nie udają lokalizacji; cache geokodera przeżywa teraz restart (zrzut na beforeExit/exit/SIGTERM+SIGINT z ponownym podniesieniem sygnału, flaga dirty czyszczona dopiero po wylądowaniu zapisu), zamykanie jest ograniczone (zatrzask pętli wyjścia, licznik generacji, LRU wg świeżości), a wyczerpany budżet geokodowania odpowiada 503 + Retry-After zamiast generycznego 502.
  • Cache-busting pakietu (CAR-145 r2+r3): powłoka przywołuje /js/bundle.js?v=<content-hash> — immutable przy dopasowaniu, no-store przy rozjeździe — likwidując 5-minutowe okno wdrożenia, w którym świeża powłoka spotykała się z cache’owanym starym pakietem. Hash i strumień współdzielą jeden deskryptor pliku (bez poszarpanych odczytów); skrócony odczyt odpowiada null zamiast awaryjnego hasha ze stat, który mógłby skazić całe wdrożenie; make-bundle zapisuje tożsamość i pliki towarzyszące .br/.gz przez tymczasowy plik z kropką + rename, więc zabity build ani nie serwuje półzapisanych bajtów, ani nie zostawia po sobie pliku tymczasowego.
  • Przepełnienie deep (CAR-146): zapisany brief badawczy, którego sama nazwa pliku przekracza viewport telefonu, nie potrafi już wypchnąć #/deep poza 390px — karta zamyka się w swoim wierszu, tytuł łamie się, a data zostaje w jednej linii; przegląd wąskiego viewportu przechodzi teraz przez #/deep z zaseedowanym, przesadnie długim fixture (jedyne ustalenie dwóch przebiegów remote-QA, zamknięte).
  • Utwardzenie pipeline v2 (recenzja CAR-116): usunięcia proszą o potwierdzenie i umożliwiają undo (z uczciwą treścią komunikatu undo), karty nie fabrykują firmy z hosta, identyfikatory wierszy opierają się na FNV-1a, liczniki operacji zbiorczych są prawdziwe, a operacje zbiorcze mają zabezpieczenie przed ponownym wejściem.

Dodano

  • Pipeline v2 (CAR-116): wzbogacone karty, widok pogrupowany i zbiorcze odrzucanie z undo; 17 nowych kluczy pipe.* trafiło do wszystkich 19 słowników od razu przetłumaczonych.
  • Raporty v2 (CAR-118): wyszukiwanie na żywo z filtrami przedziału oceny/wiarygodności/firmy/daty, sortowalne nagłówki (aria-sort), trwały widok kart z przyciskami akcji dla każdego przedziału, histogram ocen filtrujący po kliknięciu oraz zunifikowany rendering „Firma — Stanowisko” / „x.x/5” (window.ReportOps); 31 kluczy rep2.* trafiło do wszystkich 19 słowników od razu przetłumaczonych.

Uwagi

  • Każda poprawka przeszła rundę recenzji z dowodami czerwony→zielony; dwa ustalenia HIGH z recenzji AI dla pierwszego r2 pakietu (hash skróconego odczytu, atomowość plików towarzyszących) zamknął r3, a rundy CAR-143/CAR-144/CAR-142 każdorazowo ponownie zweryfikowały otwarte ustalenia swoich poprzedników.
  • Świadomie nie zrobiono: widok klastrów mapy pozostaje CAR-125 (w kolejce); przywracanie metadanych pipeline’u po stronie serwera to osobny ticket; brak wstecznych poprawek dla treści zapisanych w stanach sprzed rev-2 z v1.259.0.
  • Testy 5988 (+165); zestaw przeglądarkowy 152 zaliczone / 0 niepowodzeń / 1 opcjonalnie pominięty. Żadne źródło skanera nietknięte (rejestr 121 = 116 EN + 5 RU · 116 adapterów); 48 nowych kluczy i18n wylądowało ze swoim rozrzutem ×19 wewnątrz samych PR-ów z funkcjami.

[1.259.0] — 2026-10-25

Drugi pociąg floty agentów, sześć poprawek: daty raportów są przypinane po stronie serwera, geokoder mapy cache’uje i rozpoznaje rosyjskie miasta, pomoc ×18 przywołuje zlokalizowane etykiety przycisków, zdania interfejsu przestają mieszać języki, porównania wynagrodzeń liczone są po stronie serwera — a pakiet JS dystrybuowany jest wstępnie skompresowany (zimne ładowanie 3.1 MB → 598 KB).

Naprawiono

  • Wymyślone daty raportów (CAR-101): prompt ewaluacji przypina teraz dzisiejszą datę po stronie serwera („pole Date: MUSI być dokładnie — przepisz dosłownie; nigdy nie wymyślaj”), a fixReportDate przepisuje wymyśloną datę na dzisiejszą w każdym miejscu akceptacji (gałąź Anthropic, podproces Gemini, ogon zgodny z OpenAI, /api/deep, auto-pipeline) z ostrzeżeniem + rekordem aktywności — to korekta, nigdy odrzucenie. 349/789 raportów na produkcji miało wymyślone daty; nowe już nie mogą.
  • Geokodowanie mapy (CAR-105): cyryliczne nazwy miast w wierszach hh.ru/Habr docierają teraz do geokodera; trwały, ograniczony rozmiarem cache (data/geocode-cache.json, z blokadą withFileLock) sprawia, że już rozwiązane miasto nigdy nie sięga po dostawcę drugi raz; wywołania geokodowania mają budżet na żądanie, więc mapa wypełnia się stopniowo zamiast blokować przez 13.9 s.
  • Mieszane języki interfejsu (CAR-108): naprawiono 23 wycieki na poziomie kluczy w 17 z 19 słowników (85 wartości) — „все matching”, „только remote”, „Открыть Scan”, lejek „Evaluated → Applied…” i inne stały się pełnymi zlokalizowanymi zdaniami ponownie używającymi własnego słownictwa produktowego każdej wersji językowej. i18n-no-latin-leaks rozszerzono o tabelę fragmentów + sondę lejka (czerwony→zielony).
  • Odwrócenie werdyktu walutowego (CAR-109): porównanie wynagrodzeń liczone jest po stronie serwera w comp-compare.mjs i wstawiane w kanonicznej formie (Candidate minimum: … per YEAR (raw: …) vs JD offer: …); formy miesięczne ×12, k/к/тыс/萬 i przecinki dziesiętne normalizują się przed porównaniem; niepewna konwersja sama w sobie nigdy nie może odwrócić werdyktu (przypadek zh-TW „€80–100k ниже минимума” jest martwy). Model nigdy nic nie mnoży.
  • Etykiety przycisków w pomocy ×18 (CAR-107): zlokalizowane pakiety pomocy przywoływały angielskie etykiety („⚡ Run live”, „Save”, „Scan now”), których interfejs już nie pokazuje — 263 zastąpienia w 18 wersjach językowych, zmapowane ze źródeł widoków; docs-assistant dziedziczy tę poprawkę.

Dodano

  • Wstępnie skompresowany pakiet + cache’owalne zimne ładowanie (CAR-104): make-bundle.mjs emituje bundle.js.br (brotli q11) + .gz w czasie wydania; middleware ograniczony do pakietu negocjuje br > gz z Vary: Accept-Encoding, public, max-age=300, must-revalidate + ETag/304; z zabezpieczeniem świeżości (plik towarzyszący nigdy nie serwuje niczego starszego niż właściwy pakiet), bezpośrednie żądania artefaktów zwracają 404, CSP bajt w bajt identyczne. Zimne ładowanie: 3.1 MB → ~0.6 MB transferu (−80%); powtórne wizyty w ciągu 5 minut przenoszą ≈0 bajtów.

Uwagi

  • Wszystkie poprawki pochodzą od floty agentów z dowodami czerwony→zielony (13 + 28 + 1 + 30 + 7 nowych przypadków w ich zestawach) i przeszły rundy recenzji (CodeQL #579/#580/#584 naprawiono w kodzie — stuby URL są parsowane przez new URL().host, martwy ciąg promptu usunięto).
  • Liczby uzupełniania ocen z v1.258.0 są teraz odnotowane w CAR-129 (updated: 22, reportScoreless: 159).
  • Świadomie nie zrobiono: bez wstecznej poprawy dat dla 349 historycznych raportów (backfill byłby operacją wykonywaną za zgodą właściciela), bez widoku klastrów na mapie (CAR-125 pozostaje w kolejce za tą poprawką geokodowania).
  • Testy 5823 (+74). Żadne źródło skanera nietknięte (rejestr 121 = 116 EN + 5 RU · 116 adapterów); brak kluczy i18n (CAR-108 edytuje wyłącznie wartości istniejących kluczy).

[1.258.0] — 2026-10-25

Sześć poprawek od floty agentów w jednym pociągu: licznik firm na #/scan przestaje mieszać wszechświaty, deep research wymaga źródeł, błędy formularzy podświetlają pole, stany ładowania zyskują szkielety i natychmiastowy h1, a ewaluacje cache’ują swój 37k-tokenowy prefiks promptu.

Naprawiono

  • Licznik „Aktywne firmy” na #/scan (CAR-100): licznik zliczał odrębne firmy wśród WSZYSTKICH wierszy wyników (1554 na produkcji — sam hh.ru wnosi setki), podczas gdy mianownik zliczał firmy śledzone z zapleczem API (~90) — dwa wszechświaty w jednej frakcji. Wybrano parowanie (a): licznik zlicza teraz firmy wśród wierszy, które sam skan śledzonych firm z zapleczem API pobrał (dopasowanie po _entry ?? company; wiersze pracodawców z hh.ru/telegram wypadają); fallback przedskanowy przeniesiono do tego samego wszechświata (mógł pokazywać „104/90”).
  • Fabrykowanie w deep research (CAR-110): prompt deep niesie teraz twardy kontrakt — każde twierdzenie faktograficzne kończy się znacznikiem [source: domain.com] (nie potrafisz nazwać źródła → nie stawiaj twierdzenia; sfabrykowany znacznik jest gorszy niż napisanie unknown), nieznane fakty zapisuje się jako unknown, a raport MUSI kończyć się sekcją ## Data freshness. Kotwice świeżości: dzisiejsza data UTC + opcjonalny url firmy w POST /api/deep (ograniczony, nigdy pobierany po stronie serwera).
  • Błędy formularzy podświetlają pole (CAR-130): nieudany POST oznacza pierwsze pole formularza jako aria-invalid + .is-error i ustawia na nim fokus (WCAG 3.3.1); oznaczenie czyszczone przy edycji. Podpowiedź przy błędzie sieci jest świadoma wdrożenia — loopback zachowuje podpowiedź z komendą deweloperską, a wdrożony origin dostaje „Serwer nie odpowiada.” zamiast porady bash web-ui/bin/start.md (baner połączenia nosił to samo zaszyte na sztywno sformułowanie).
  • Stany ładowania (CAR-112): #/map i #/tracker renderują swój h1 natychmiast (cel fokusu routera istniał dopiero po nadejściu danych), a współdzielony helper szkieletów (Skeleton.rows, wiersze aria-hidden z migotaniem wewnątrz regionu role="status" ponownie używającego common.loading) zastępuje goły tekst „Ładowanie…” na trackerze, w wynikach skanu i w powłoce mapy; prefers-reduced-motion zatrzymuje pulsowanie.
  • Cache’owanie promptu ewaluacji (CAR-111): buildEvaluationPromptParts dzieli ~37k-tokenowy prompt na stabilny bajtowo prefiks (CV + profil + pliki trybów + instrukcje) i ogon z JD; ścieżka Anthropic wysyła [prefix + cache_control: ephemeral] + [JD] — prefiks rozliczany jest stawką odczytu z cache (≈10× taniej) przy każdym wywołaniu po pierwszym. Brakujący/niedopasowany prefiks otwarcie wraca (fail open) do bajt w bajt identycznego starego żądania; kaskada zgodna z OpenAI pozostaje nietknięta (tam cache po stronie serwera).

Uwagi

  • Wszystkie sześć poprawek pochodzi od floty agentów z dowodami czerwony→zielony (5 + 7 + 7 + 7 + 8 nowych przypadków) i rundami recenzji; pierwsze alerty CodeQL dla CAR-111 (#579/#580) naprawiono w kodzie — testowy stub parsuje host z URL zamiast dopasowania podłańcuchowego, a martwy ciąg pełnego promptu usunięto.
  • Uzupełnianie ocen wykonano na produkcji (endpoint z v1.256.0, za zgodą właściciela): updated: 22, missingReport: 0, reportScoreless: 159 — 159 wierszy bez oceny wskazuje na raporty, których nagłówki poprzedzają blok maszynowy albo niosą nieparsowalne formaty oceny; do odzyskania wyłącznie ponowną ewaluacją lub szerszym przebiegiem parsera (odnotowane w CAR-129).
  • Świadomie nie zrobiono: bez zmiany nulls-last dla kolumny dojazdów (istniejąca od dawna dziwność Infinity przy sortowaniu malejącym), bez wstecznej ponownej wyceny starych rekordów użycia, bez podświetlania w stylu .is-error dla formularzy filtrów skanu (CAR-130 ograniczone do współdzielonego helpera submit widoku mode-page + podpowiedzi w api.js).
  • Testy 5749 (+36). Żadne źródło skanera nietknięte (rejestr 121 = 116 EN + 5 RU · 116 adapterów); brak kluczy i18n (podpowiedź CAR-130 ponownie używa conn.down; region szkieletu ponownie używa common.loading).

[1.257.0] — 2026-10-25

Dwie poprawki od floty agentów: asystent pomocy w aplikacji rozumie dewanagari i tamilski, a strona użycia pokazuje, ile Hermes faktycznie kosztuje.

Naprawiono

  • Wyszukiwanie w asystencie pomocy dla hi/ta (CAR-103): klasa znaków słowa w tokenizatorze słów kluczowych docs-assistant była zdefiniowana jako [\p{L}\p{N}\u30fc]+ — bez znaków łączących (combining marks). Każda matra dewanagari (ा ै ्…) i każdy tamilski znak samogłoskowy (ே ை ்…) rozbijały słowo na fragmenty; reguła długości wyrzucała krótkie fragmenty (zapytanie po hindi dopasowywało 0 sekcji), a dłuższe słowa dekapitowały się w śmieci kolidujące z niepowiązanymi sekcjami. Klasa zachowuje teraz \p{M}; ścieżka bigramów CJK pozostaje nietknięta. hi „मैं स्कैन कैसे चलाऊं?” i ta „ஸ்கேன் எப்படி இயக்குவது?” pobierają właściwe sekcje z dostarczonych pakietów.
  • Koszt użycia u Hermesa (CAR-106): normalizeUsage() spłaszczało użycie dostawcy do {in, out} i po cichu gubiło raportowany przez bramkę cost — #/usage pokazywało $0.0000 przy 9.5 M tokenów Hermesa (jego wiersz w tabeli cen to 0/0). Kształt rekordu użycia zyskuje opcjonalne, wstecznie kompatybilne pole cost?; agregator preferuje na rekord koszt raportowany przez dostawcę i sięga po szacunek z tabeli cen tylko wtedy, gdy go brakuje; śmieciowe/ujemne wartości są odrzucane, nigdy nie są fabrykowane.

Uwagi

  • Obie poprawki pochodzą od floty agentów z dowodami czerwony→zielony (3 + 5 nowych przypadków; 14/14 i 10/10 zielonych; sąsiednie zestawy 78/78 i 61/61). Pierwsze PR-y (#470/#471) miały przestarzałą bazę worktree, która kolidowała ze squash-merged v1.256.0 — zastąpione czystymi cherry-pickami (#472/#473).
  • Świadomie nie zrobiono: bez wstecznej ponownej wyceny historycznych linii data/llm-usage.jsonl (nie niosą pola cost; korzystają tylko nowe rekordy).
  • Testy 5713 (+8: docs-assistant ×3, usage ×5). Żadne źródło skanera nietknięte (rejestr 121 = 116 EN + 5 RU · 116 adapterów); brak kluczy i18n.

[1.256.0] — 2026-10-25

Jakość danych trackera: stanowisko nigdy nie ląduje w kolumnie firmy, tablica ofert nigdy nie ląduje w kolumnie pracodawcy, wiersze bez oceny przestają wysuwać się na czoło — a endpoint jednorazowego użycia uzupełnia brakujące oceny z samych raportów.

Dodano

  • Uzupełnianie ocen wstecz (CAR-129): POST /api/tracker/backfill-scores wypełnia komórkę Score wierszy, których podlinkowany raport niesie sparsowalną ocenę (181 ocenionych wierszy miało raport, ale nie miało oceny). Wiersze z oceną, jawne sentinele (N/A), wiersze bez raportu i raporty bez oceny nie są nigdy ruszane; przepisywana jest wyłącznie komórka Score, pod blokadą pliku; kształt oceny jest walidowany w miejscu zapisu i normalizowany do konwencji trackera X.X/5; przebieg jest idempotentny i zwraca {ok, updated, missingReport, reportScoreless}.

Naprawiono

  • Stanowisko nigdy nie jest firmą (CAR-128): guessCompanyRole traktowało LEWĄ stronę linii nagłówka z myślnikiem jako firmę, ale tablice piszą obie kolejności — „Senior Frontend Engineer - Grafana Labs” lądowało jako stanowisko ZAPISANE jako firma (13 wierszy: Grafana, CircleCI…). Heurystyka słów kluczowych stanowiska z granicami słów wybiera teraz właściwą stronę, a typ zatrudnienia nigdy nie staje się pracodawcą (dla „Senior Engineer - Remote (EU)” nie zapisuje się niczego, zamiast „Remote (EU)”).
  • Tablica ofert nigdy nie jest pracodawcą (CAR-127): fallback sluga domenowego zapisywał wiersze hh.ru jako „hh” (120 wierszy). Slugi hh/habr trafiają na listę „to nie pracodawca”; wnioskowanie o pracodawcy ze środka zdania („в компании X”, „X ищет”) uruchamia się teraz także dla hostów tablic ofert (hh.ru/kz/uz/by, habr.com) — tam, gdzie tekst strony nazywa prawdziwego pracodawcę. Po drodze znaleziono korzeń błędu: ASCII \b/\w w tych wzorcach wnioskowania nigdy nie łapały cyrylicy — martwe bez śladu od v1.248.4; zastępują je Unicode lookbehindy i klasy \p{L}.
  • Wiersze bez oceny sortują się na końcu (CAR-129): sortowanie po ocenie w trackerze używało sentinelu -1, więc przy domyślnym sortowaniu rosnącym każdy wiersz bez oceny wysuwał się przed każdy oceniony. Teraz nulle lądują na końcu w obu kierunkach (FILTR po ocenie zachowuje swoje -1 — „brak oceny nie przechodzi filtra ≥4” to tam poprawna semantyka).

Uwagi

  • Historyczne wiersze NIE są migrowane przez to wydanie: poprawki parsera dotyczą nowych ocen; oceny da się odzyskać endpointem backfill, natomiast 120 komórek pracodawcy „hh” wymaga ponownej oceny, a nie przepisania.
  • Wpleciono rundę recenzji opus-5-5: niezakotwiczony wzorzec „X ищет” wypadł przed wydaniem (dowolny ciąg wielką literą przed czasownikiem zostałby zapisany jako pracodawca — niezmiennik no-fabrication), dodano zakotwiczenia na początku zdania („В…”), a zapis backfill sprawdza ponownie komórkę docelową (po ręcznych edycjach istnieją zduplikowane wiersze z tym samym #), zachowuje liczbę kolumn ręcznie zniekształconego krótkiego wiersza i zatrzymuje się na pierwszej linii spoza tabeli. Kropka w nazwie z kropką („Сбер. IT”) jest nieodróżnialna od kropki zdaniowej dla zakotwiczenia „в компании” — zapisywany jest konserwatywny prefiks („Сбер”); wzorzec zakotwiczony czasownikiem łapie pełną formę.
  • Świadomie nie zrobiono: bez wydzielenia komparatora z tracker.js do testowalnej jednostkowo biblioteki (bramka source-static zostaje; odnotowane w CAR-129 jako follow-up), bez zmiany nulls-last dla kolumny dojazdów (istniejąca od dawna dziwność Infinity przy sortowaniu malejącym), bez migracji danych dla wierszy „hh”.
  • Testy 5705 (+10: 5 testów tożsamości w auto-pipeline-jd-gate, 2 CAR-128, bramka sortowania CAR-129, 4 backfill w tym przypięcie wrogiej ścieżki — minus zastąpione przypadki v1.248.x). Żadne źródło skanera nietknięte (rejestr 121 = 116 EN + 5 RU · 116 adapterów); brak kluczy i18n.

[1.255.2] — 2026-10-24

Trzy poprawki widoczne dla użytkownika, z live regression i raportu o awarii na produkcji: awaria renderowania #/scan, ślepe sprawdzenie języka wietnamskiego i powtarzająca się utrata bloku podsumowania zh-TW.

Naprawiono

  • Awaria #/scan (CAR-99): regeneracja bramek zliczających od v1.253.0 zapisywała literał FALLBACK_SOURCES z podwójnym przecinkiem na końcu każdego wpisu — 120 dziur w tablicy (elision holes). new Set(FALLBACK_SOURCES.map((s) => s.value)) w widoku skanu trzymało więc undefined, a id.length klasyfikatora firm rzucało TypeError: Cannot read properties of undefined (reading 'length') przy każdym renderze strony (złapane przez logbuf na produkcji). Dziury usunięto, a nowa bramka (4 specyfikacje, zweryfikowana na czerwono) wykonuje plik i failuje na każdej dziurze, bezużytecznym wpisie lub undefined w Secie identyfikatorów adapterów — tekstowa bramka dryfu nie widziała tej klasy.
  • Ślepe sprawdzenie języka vi (CAR-97): wietnamski jest zapisem łacińskim i nie miał wpisu w tabeli stop words live-QA, więc „stop words vi” liczyło angielskie trafienia, a wietnamska odpowiedź czytała się jako report not in vi (live regression: vi 2, en 2). Wietnamski ma teraz własną dziesięciowyrazową tabelę słów funkcyjnych — czysto wietnamski raport przechodzi, angielski nadal failuje.
  • zh-TW tracił blok SCORE_SUMMARY (CAR-98): końcowe przypomnienie językowe mówiło tylko, że format maszynowy nie może być tłumaczony, nigdy że blok podsumowania musi istnieć — krótki raport zh-TW (5983 znaki) niósł bloki A–G, ale pomijał ten blok całkowicie (nawrót klasy v1.239.2). Dyrektywa otwierająca i końcowe przypomnienie stwierdzają teraz, że blok jest obowiązkowy, a bez niego raport jest nieważny.

Uwagi

  • To wydanie celowo nie zmienia żadnego źródła skanera, liczby rejestru (121 = 116 EN + 5 RU · 116 adapterów) ani okablowania dostawców — to wydanie wyłącznie poprawek, więc bramki zliczające są nietknięte.
  • Testy 5695 (+9: car99-fallback-holes ×4, car97-vi-lang-check ×4, niezmiennik promptu CAR-98 ×1). Przeglądarka 143/143. Ponowne sprawdzenie live vi/zh-TW jedzie z regresją po wdrożeniu.

[1.255.1] — 2026-10-24

Dwie rundy poprawek recenzenckich: recenzja Opus lokalizacji wietnamskiej (9 ustaleń) i recenzja drugiego przebiegu poprawek CAR-91/92 (5 imperatywów) — obie zamknięte testami czerwony→zielony.

Naprawiono

  • Runda recenzji lokalizacji vi (ciąg dalszy CAR-88): glif hangul (신), który wyciekł do project.subtitle / project.roleHint, poprawiony (độ khớp tín hiệu), z bramką odrzucającą dowolny glif CJK/Kany w wartości vi, której słownik EN nie niesie; sześć adresów URL markdownu ze spacjami w docs/help/vi.md (what-is career-ops, apply for a job, set up playwright i trzy kolejne) połączono łącznikami z prawdziwymi slugami przewodnika, z bramką no-spaces-in-URLs.
  • Granice nagłówków oceny (CAR-92 r2 H1): &, ., /, ' są teraz znakami słowymi w lewej granicy litery bloku — ## Q&A, ## Plan B, ## Ph.D. requirement, ## E-commerce nie rejestrują się już jako bloki A/B/D/E; goły terminator końca wiersza jest akceptowany tylko po tokenie słowa bloku (Block/блок/블록/…); ASCII - opuścił klasy terminatorów zapisanych słownie, więc nagłówki E-commerce/ई-मेल przetrwają.
  • Raporty numerowane ukraińsko-rosyjskimi literami (CAR-92 r2 H2): detektor sekwencji А Б В Г Д Є Ж jest teraz wspólnym helperem; gdy znajdzie 3+ liter sekwencji na poziomie nagłówka, ten poziom staje się poziomem referencyjnym cuttera — literowane podsekcje ### A. nie tną już raportu na bloku Б.
  • Cykl życia przenoszonych wierszy (CAR-92 r2 M1): wiersze, które poległe źródło niesie do następnego skanu, dostają pieczęć carriedSince, są usuwane po 30 dniach lub 5 kolejnych przeniesieniach i dopisywane po świeżych wierszach zamiast po cichu kumulować się w nieskończoność.
  • Mianownik i legitimacy syntez Gemini (CAR-92 r2 M2) oraz ścieżka body-score podprocesu (M3): odczytane z pliku ustaleń recenzji, naprawione z testami czerwony→zielony.

Uwagi

  • Frazy liczby adapterów w banerze „Najnowsze wydanie” README.vi, które recenzja oznaczyła, żyją w banerze Poprzednie wydanie i już teraz są kopią lustrzaną EN README bajt w bajt — nietknięte, by zachować parzystość EN↔vi (udokumentowane w treści commita).
  • Podłoga testów: 5642 → 5686 (+26: eval-validate-opus-r2, scanner-carryover-r2, asercje bramek vi). Rejestr bez zmian: 121 źródeł (116 EN + 5 RU) · 116 adapterów.

[1.255.0] — 2026-10-24

Wietnamski (Tiếng Việt) dołącza jako 19. język interfejsu — słownik 1525 kluczy w pełnej parzystości z EN, wykrywanie vi/vi-VN, pełny pakiet pomocy, kopie lustrzane README i CHANGELOG, integracja z landingiem cvstart.org oraz 🇻🇳 w przełączniku języka.

Dodano

  • Wietnamski (vi) — 1525/1525 kluczy w pełnej parzystości z en; detect() przyjmuje vi i vi-VN; wietnamski jest LTR (nigdy nie trafia do RTL_LANGS). „Pipeline” zostaje „Pipeline” — standardowe zapożyczenie techniczne, na białej liście.
  • Pełny docs/help/vi.md (33 H2 / 125 H3), plus kopie lustrzane README.vi.md i CHANGELOG.vi.md oraz wietnamskie ciągi szkieletowe w prompts.mjs (LOCALE_NAMES + SCAFFOLD_STRINGS) — wyjście LLM po wietnamsku działa od razu.
  • Landing cvstart.org po wietnamsku — site/src/i18n/vi.json, wpis locale w sitemap i zrzut dashboard-vi.png; przełącznik języka dostaje 🇻🇳 (19 pozycji).
  • Bramki wyliczeniowe 18 → 19 — LANGS, sondy detect, audyt i18n, parzystość changeloga, blok tłumaczeń README, locale-sweep — plus red-first tests/i18n-vi-locale.test.mjs (139 linii).

Uwagi

  • Landing cvstart.org dostaje vi — świadome odstępstwo od precedensu ta (tamta wersja trzymała landing na 17 celowo); udokumentowane w specyfikacji wydania.
  • vi jest w piśmie łacińskim, więc bramka no-latin-leaks nie ma zastosowania (pilnuje locale niełacińskich); łacińskie słownictwo techniczne to tu norma.
  • Podłoga testów: 5634 → 5642 (1 pominięta = opcjonalny przeglądarkowy test przechwytywania układu, bez zmian).

[1.254.0] — 2026-10-24

Wydanie utwardzające z rundy recenzji maksymalnym modelem: snapshot skanera nigdy więcej nie traci wierszy, jedenaście naruszeń niezmienników warstwy LLM naprawiono, dwadzieścia trzy must-fix SPA lądują, a ATS Paylocity dołącza do skanera — rejestr dostarcza teraz 121 źródeł (115 EN + 5 RU) z 116 adapterami.

Dodano

  • ATS Paylocity (rodzic #5687): tablice per tenant recruiting.paylocity.com, martwa tablica 302 → JobNotFound mapowana na 404, by kwarantanna przeniosła wpis w stan spoczynku, limit max_jobs z flagą ucięcia. Rejestr: 121 źródeł = 116 EN + 5 RU · 116 adapterów; gate liczników regenerowane.

Naprawiono

  • Bezpieczeństwo snapshotu skanera (R-12): skan, który niczego nie próbuje, teraz ZACHOWUJE snapshot (nothing scanned); pełne zastąpienie przenosi stare wiersze źródeł, które poległy — ostępowane per wpis — ponownie przez AKTUALNE filtry, lądując tylko w filtered.
  • Jedenaście naruszeń niezmienników warstwy LLM: dyrektywa językowa otwiera I zamyka prompty deep/mode; podproces Gemini przekazuje --lang, wyjście niezerowe → 502, nie wycieka stderrem do klienta, trzyma 300 s i rejestruje usage; manual fallback niesie URL oferty; truncation i ostrzeżenia bundla wynurzają się w /api/mode; spend tier nie jest już nadpisywany przez klienta; rozłączenie klienta przerywa wywołanie dostawcy w locie; cutter powtarzalnych nagłówków nie niszczy już ważnych raportów; ekstraktory score/legitimacy zgodne z walidatorem; ukraińska sekwencja i arabskie wa zaostrzone.
  • Runda rewizji Opus 5-5 NA samych poprawkach (8 imperatywów): wielo-literowa rejestracja cuttera, szersze terminatory nagłówków, okablowanie abortu podprocesu Gemini, ostępowana atrybucja przenoszenia, przeniesione wiersze przechodzą aktualne filtry, poziom referencyjny po liczbie różnych liter.
  • Dwadzieścia trzy must-fix SPA w widokach sourcing (append pagera jednostronicowego, klawiatura wierszy pipeline, przywracanie filtrów saved-search, reset selecta source, cofanie domyślnej wartości w config, wycieki listenerów, close SSE na terminalu, teardown scan-runnera, goły fetch, nieudane wczytania wyglądające jak puste, kolizja globalna, zachowanie fokusu) i assist (martwy deep-link help, wycieki help, ponowne uzbrojenie blank-overwrite w two-pager, single-flight płatnych uruchomień batch/deep/mode, ciche końce streamów, wieczne spinnery na błędach, wiersze-widma nieudanych filtrów, duplikaty docs-fab + język).

Uwagi

  • Cała runda była recenzowana przez Opus 5-5 z maksymalną surowością — porty przed merge’em (21 ustaleń, 13 naprawionych) i same poprawki post-hoc (8 imperatywów, wszystkie tutaj z testami czerwony→zielony).
  • Podłoga testów: 5262 → 5634 (372 nowe specyfikacje w źródłach, skanerach, warstwie LLM i SPA).

[1.253.1] — 2026-10-24

Dwa HIGH-owe znaleziska bezpieczeństwa z recenzji maksymalnym modelem naprawione: literały IPv6 nie omijają już SSRF-gate skanera, a regex escape markdownu CV nie backtrackuje już kwadratowo.

Naprawiono

  • Literały IPv6 omijały SSRF-gate (http-json.mjs): literał IPv6 w nawiasach sprawiał, że dns.lookup rzucał, a gate fail-open. Teraz nawiasy są zdejmowane, a literał klasyfikowany przez isIP — bez DNS, bez fail-open.
  • ReDoS w escape markdownu CV (security.mjs): wzór backtrackował kwadratowo — < + ~100k spacji kosztowało ~16 s; teraz ~1 ms na płaskiej ograniczonej klasie. Wszystko escapowane wcześniej jest escapowane dalej.

Uwagi

  • Obie poprawki niosą testy czerwony→zielony (3 nowe przypadki IPv6 + ReDoS z limitem czasu; 5511 testów, +7).
  • Pliki źródłowe skanera nie są dotknięte — gate żyje we wspólnym transporcie.

career-ops-ui v1.267.1 · page 1/10 · mirror of the project changelog for cvstart.org