Changelog

GitHub

Ogni cambiamento rilevante, release dopo release. Lo stesso file è distribuito nel repository ed è tradotto in tutte le 19 lingue.

[1.267.1] — 2026-11-04

Corretto

  • Riparazione del treno di release (i gate CI di v1.267.0) — la catena dei conteggi dei test in PROJECT-CONTEXT non si spezza più alla testa di v1.267.0 (il formato freccia che l’eval grader matcha), i prompt QA sono riorganizzati (un prompt vivo per release, v1.266.0 archiviato) e la copertura per file viene portata sopra il ratchet 98/90: il renderer del salario di applicantpro perde un fallthrough irraggiungibile (salaryRangeOf dimostrabilmente produce undefined, {min}, {max} o {min,max}) con i rami unilaterali ≥/≤ ora pinati attraverso il flusso fetch, e la suite board-response-cache pina il bypass no-store, il 304 fornito dal chiamante contro un board non salvato e l’eviction a MAX_ENTRIES.
  • Test: il conteggio live è 7395 (le suite dell’ondata v1.266.0/1.267.0 portano più spec di quanto le note precedenti tracciassero — la catena è ri-ancorata al piano misurato: 7392 dopo l’ondata, + 3 test di gate in questa patch); copertura 98.51 riga / 90.35 ramo.

Note

  • Il tag v1.267.0 resta puntato sul commit rosso del merge — non viene ripuntato (il server rifiuta i tag ripuntati); v1.267.1 è il veicolo di deploy.

  • Riparazione in patch del treno v1.267.0: gate CI verdi, l’albero del codice non è cambiato in sostanza.

[1.267.0] — 2026-11-04

Aggiunto

  • Quattro nuove sorgenti di scansione — GermanTechJobs, Darwinbox, Keka, ApplicantPro/isolved (registro 125 → 129 = 124 EN + 5 RU · 124 adapters) — la seconda ondata di parent-sync contro career-ops @ 7d8feb6d (87 commit upstream). GermanTechJobs (#6346): RSS a livello di board su germantechjobs.de/rss (~626 elementi in un’unica richiesta); il datore è l’ultimo segmento " @ " del titolo — un titolo senza di esso viene scartato, mai archiviato sotto il board; solo selezione esplicita via provider:. Darwinbox (#6416): JSON alljobs senza autenticazione dietro <tenant>.darwinbox.in, l’id azienda arriva dalla careers URL, camminata POST paginata (50/pagina, max_pages 20/200) con l’arresto su pagina corta letto dal numero di righe dichiarato dalla sorgente stessa. Keka (#6199): due richieste — una shell careers con redirect:'manual' il cui script nomina l’UUID del feed (un tenant sconosciuto risponde 302 verso TenantNotFound.html e si legge come un 404 nominato), poi l’intero inventario aperto in un unico array embed-jobs. ApplicantPro / isolved (#6252): il domainId numerico preso dal bootstrap, poi {success, data:{jobs, jobCount}}; jobCount > rows avvisa che l’elenco è incompleto; applicantpro: { fetchDetails: true } opt-in arricchisce da JSON-LD con pausa di 250 ms.
  • Riuso delle risposte dei board via ETag (#6105) — nel corso di una singola scansione, una risposta di board recuperata negli ultimi 15 minuti viene riusata così com’è e quelle più vecchie vengono rivallidate con If-None-Match (il 304 conserva il corpo); la chiave di cache copre metodo + URL + header delle credenziali + corpo, le letture sovrapposte collassano sulla promessa in volo, e CAREER_OPS_HTTP_CACHE=0 / _TTL_MS la scavalcano. In memoria per esecuzione di scansione (web-ui non ha un contratto di cache su disco) — deviazione registrata.

Corretto

  • Le date su quattro board (#6274) — remoteok, remotive, workingnomads e IBM ora emettono una data di pubblicazione, così il filtro «Posted within» vi funziona; il timestamp naive di remotive è normalizzato in UTC (il suo bug di età calcolata per macchina era attivo), il _source di IBM ora richiede davvero dcdate.
  • Una chiave di portals.yml scritta male viene rifiutata (#6107) — la scansione EN ora lancia un errore nominato (file + chiave + suggerimento della chiave più vicina, Levenshtein ≤ 2) prima di qualsiasi fetch, invece di ignorare in silenzio titel_filter:.
  • getro continua a camminare oltre un vecchio pin in evidenza (#6406) — un annuncio stantio fissato in evidenza viene comunque scartato ma non termina più la paginazione; la camminata si ferma su una pagina corta reale.

Note

  • Deliberatamente non fatto: il seen-filter dello scanner RU non è sensibile alla lingua e il suo percorso di parse dei portals non esegue il gate della chiave sbagliata (hand-off registrati nella spec dell’ondata — nessun board RU emette ancora righe per lingua); remoteok conserva la sua stringa di data con offset invece di normalizzarla in UTC (la sua forma in produzione è deterministica). Test 7096 → 7243; Playwright 173 pass / 0 fail / 1 opt-in skip; registro 129 = 124 EN + 5 RU · 124 adapters (tutte le porte di conteggio rigenerate dal registro vivo).

[1.266.0] — 2026-11-01

Aggiunto

  • Le versioni linguistiche di Personio smettono di mangiarsi a vicenda (CAR-223: genitore #4789 + #5044 + #5285) — lo stack rimandato, eseguito come propria consegna. Lato scansione (#4789): scan_history.dedup_include_language: true (opt-in rigoroso — OFF è byte-identico) fa sì che le versioni linguistiche di uno stesso annuncio sopravvivano al dedup tramite la macchina a varianti della cronologia delle visite (languageFormsFromUrl / recordUrlVariant / isUnseenLanguageVersion); la chiave canonica rimuove i parametri language/lang/locale. preferred_languages (#5285): ordina le righe di versione di un annuncio con le preferite al primo posto (stabile, ordine del provider in caso di parità) — indipendente dall’interruttore (OFF conserva la versione preferita, ON conserva ogni versione in quell’ordine), con un port di validatePreferredLanguages da validate-portals. fan-out personio (#5044): la pagina careers viene recuperata senza il forzamento ?language=en (un ?language=xx proprio del tenant viene onorato) ed emette una riga per versione linguistica con language + URL ?language=<code>; dedupIncludeLanguage aggiunge recuperi per lingua (tetto 5, con pausa); i fallback /xml e job-link restano invariati. recruitee guadagna la stessa emissione language + preferred_languages (opzioni o voce). Gli helper condivisi vivono in server/lib/language-preferences.mjs.

Note

  • Hand-off registrati, deliberatamente non fatto: il seen-filter dello scanner RU non è sensibile alla lingua e nessun board RU emette ancora righe per lingua; il mirror client url-key.js e il cablaggio della validazione della rotta portals restano aperti. Test 7096 → 7203; registro invariato 125 = 120 EN + 5 RU · 120 adapters.

[1.265.0] — 2026-11-01

Aggiunto

  • Due nuove sorgenti di scansione — Apple e Bulldogjob (registro 123 → 125 = 120 EN + 5 RU · 120 adapters) — ondata di parent-sync contro career-ops @ fe857ecf. Apple (jobs.apple.com, #5496 + #6196): il sito è un’app React Router SSR senza un’API JSON utilizzabile, così la sorgente legge il blob di idratazione della route di ricerca ordinaria (window.__staticRouterHydrationData); il reperimento è guidato dalla voce (apple.queries con ordinamento per pertinenza + assi apple.teams, nessun default — una voce senza nessuno dei due lancia un errore), le pagine sono limitate da max_pages (2 predefinito, tetto 50) con pausa di 200 ms, ogni segmento URL è codificato a prova di surrogate e un annuncio che Apple etichetta PIPE porta nello snippet il suggerimento «può essere un talent pipeline» — nulla viene filtrato su di esso. Bulldogjob (bulldogjob.pl, #6253): nemmeno il board polacco ha un’API JSON — i listing trasportano __NEXT_DATA__ (50/pagina, totalCount); il careers_url della voce è la ricerca costruita sul sito (i filtri vivono nel percorso), ogni richiesta porta un /page,N esplicito e la camminata si ferma su una pagina corta, sul totale dichiarato o su max_pages (25 predefinito, tetto 100) con etichetta di troncamento sui board parziali.
  • Rework della paginazione IBM (#6273) — la camminata fissa a 600 record diventa max_pages (20 predefinito, tetto 300, override per voce) con pausa di 200 ms tra le pagine e retry per pagina via fetchJsonWithRetry; una prima pagina fallita lancia un errore, una pagina successiva fallita conserva il raccolto e nomina la pagina, e solo una pagina completa al tetto proprio della voce avvisa «raise max_pages».

Corretto

  • justjoin data le offerte con lastPublishedAt (#6254) — il publishedAt dell’API candidati avanza a ogni aggiornamento del datore, così gran parte del board portava la data di oggi e max_posting_age_days lasciava passare annunci di settimane prima; ora vince la data di pubblicazione precedente, con fallback quando manca o non si parsa.
  • jobvite raggruppa le righe che condividono un posting URL (#6127) — un feed pubblico restituisce una riga <job> per città per un unico detail URL; il parser teneva la prima città e lascava contare il resto come duplicati. Ora i fratelli contribuiscono solo con le località, unite con · nell’ordine del feed, primo titolo/data resta e «remote» è rivalutato sulla località unita.
  • Liveness: un rung per UltiPro (#6090) — UKG non ha un endpoint JSON per annuncio e risponde 200 anche sui chiusi, così tutti i 57 annunci UltiPro chiusi leggevano uncertain. La pagina di dettaglio incrusta il record: OpportunityIsClosed true/false → expired/active, l’avviso «opportunity unavailable» → expired, tutto il resto resta al browser. Il banner di Built In «Sorry, this job was removed» diventa hard-expired (#6336) — la pagina conserva il JD completo e il controllo APPLY; ora vince il banner, e il badge fratello «Job removed» senza «sorry» non corrisponde.

Note

  • Deliberatamente non fatto: la metà parent-side della correzione jobvite sul compilatore di località di scan.mjs (web-ui documenta il compilatore USPS come no-port) e il campo note del padre per il suggerimento PIPE di Apple (il job shape di web-ui non ha note; viaggia nello snippet). Test 7096 → 7135 (+39); Playwright 173 pass / 0 fail / 1 opt-in skip; coverage gate ≥ 98/89; registro 125 = 120 EN + 5 RU · 120 adapters (tutte le porte di conteggio rigenerate dal registro vivo).

[1.264.3] — 2026-11-01

Corretto

  • Onda di irrobustimento del rate-limit (LOW nº 1–3 da REVIEW-2026-10-31-v1.264.1) — writeRateLimit() (express-rate-limit@7.5.1, 60 req/min route×IP, 429 JSON + Retry-After) copre ora tutti i 47 endpoint di mutazione (prima 2): 9 guardie llmRateLimit mal delimitate sono sostituite (/api/config — riscrittura del .env!, PUT /api/batch, /api/batch/merge, outcome, followup/seed, assessments, stats/snapshot, mock-interview/save, networking/save), 3 sono impilate prima del bucket LLM sui percorsi più costosi (/api/evaluate, /api/deep, /api/auto-pipeline) e 33 registrazioni nude vengono collegate (editor CV/profile/modes, tutte le scritture del tracker, pipeline POST/restore/DELETE, jds, 7× /api/run/* con una sola modifica al ciclo, posting-guard, Playwright-PDF inline, portals toggle/health/track, discover, reports, export/docx, two-pager, career-plan, memory e le tre rotte DELETE). /api/apply-helper resta in allowlist senza limite (calcolo locale puro, fissato); 16 rotte puramente LLM mantengono il bucket condizionale LLM per progetto. Un tripwire di completezza (tests/rate-limit-coverage.test.mjs, red-first a 27 nude) fa fallire il CI davanti a qualsiasi futura registrazione di mutazione senza throttle.
  • TRUST_PROXY opt-in + validazioni riarmate (LOW nº 1–2) — app.set('trust proxy', N) accetta un hop-count dall’env (mai boolean true — altrimenti la chiave si costruisce sull’estremità sinistra dell’XFF controllata dall’attaccante); senza valore predefinito, il loopback conserva la degenerazione documentata con chiave su socket. validate: false diventa un writeValidateConfig() mirato: viene disattivata solo xForwardedForHeader (l’XFF di Caddy è ignorato per progetto senza trust proxy); le altre validazioni — incluso trustProxy — tornano rumorose, così una futura configurazione errata trust proxy: true si manifesta come ERR_ERL_PERMISSIVE_TRUST_PROXY e non in silenzio. Il keyGenerator personalizzato è stato rimosso deliberatamente: express-rate-limit lega le proprie validazioni proxy al generatore predefinito, e l’isolamento per rotta non cambia (un MemoryStore per chiamata di factory).
  • Il feedback di copia di cvstart.org dura 2 s (CAR-141) — lo stato «Скопировано ✓» ora permanece 2 secondi secondo il criterio di accettazione (prima 1,5 s), con pin red-first in tests/site-copy-feedback.test.mjs. Chiude l’ultimo criterio del CAR-141 riparabile da agente; la ri-registrazione del video demo resta rimandata per decisione del proprietario.

Modificato

  • L’aiuto dice 19 lingue (×19) — le frasi del §19 «Localizing the app» e del §32 «Run it from OpenWorker» non restano più due localizzazioni indietro: ogni bundle dice ora 19, con தமிழ் e Tiếng Việt aggiunti a ogni enumerazione nello stile proprio del file (ar usa la cifra scritta «التسع عشرة»), e il residuo «cả-17» del §32 di vi.md è corretto a sua volta. I cancelli di struttura (33 H2 / 125+ H3) restano byte-stabili.
  • Igiene di stato — AGENTS.md indica v1.264.2 / 7082 test (prima v1.86.x / 1566); PLAN.md segna le consegne 1–7 come Shipped e il suo paragrafo del treno dice docs ×19; il commento di StatsBar.astro descrive ciò che facts.adapters contiene davvero (123 = totale delle fonti, nome storico della chiave conservato per i consumatori); l’intestazione di i18n.js dice 19 lingue; il QA prompt v1.264.2 porta la copertura reale (98.45/90.05) e l’aritmetica di Playwright (176 = 174 harness + 1 opt-in skip + 2 suite a livello di script).

Note

  • Deliberatamente non fatto: l’onda di parent-sync secondo la port-list registrata resta in BACKLOG — il fork deve prima sincronizzarsi past upstream a9476866 (7 dei 10 commit della lista non sono ancora nell’albero locale del genitore; IBM/UltiPro/Bulldogjob/apple con portata S–M, personio language-dedup rimandato a una propria consegna). La ri-registrazione del video demo del CAR-141 resta consapevolmente rinviata dal proprietario («видео не надо пока», 2026-11-01).
  • Test 7082 → 7096 (+9 tripwire di copertura + 5 trust-proxy); Playwright 173 pass / 0 fail / 1 opt-in skip (+2 pin dei chevron dentro casi esistenti); coverage 98.46 line / 90.10 branch; evals 14/0/1skip; registro invariato 123 = 118 EN + 5 RU · 118 adapters.

[1.264.2] — 2026-11-01

Corretto

  • Le intestazioni di gruppo del sidebar entrano nel contratto di troncamento (CAR-219) — le etichette dei toggle di gruppo (.nav-v2-toggle > span) ora si troncano con un’ellissi e portano un tooltip localizzato attraverso lo stesso meccanismo syncLabelTitles() degli elementi nav del CAR-203; il chevron non si restringe mai, il toggle resta cliccabile, l’RTL tiene. Pin red-first in tests/nav-v2.test.mjs (+1 → 7082 test).

Modificato

  • La copia di cvstart.org arriva in tutte le 19 lingue (CAR-220) — meta.helpDesc, helpTeaser.c1.desc e faq.a2 sono tradotti in ogni località del sito (in v1.264.1 erano EN-only di proposito); GitHub Pages ha pubblicato dal vivo la copia aggiornata su cvstart.org.
  • Igiene di backlog + review (CAR-221/222) — le sei voci «port when merged upstream» sono chiuse: tutti e sette i PR upstream sono mergiati, quattro voci erano già portate, due sono lato padre. Arriva docs/reviews/REVIEW-2026-10-31-v1.264.1.md (0 HIGH / 0 MED, tre follow-up LOW annotati nel BACKLOG) e viene registrata la port-list della parent-sync (6 PORT / 3 VERIFY / il gap della fonte apple; coda upstream di 118 commit @ VERSION 1.38.0).

Note

  • La correzione dello stamp dei mirror del changelog (92a05fcf) viaggia in questo tag: ogni mirror paginato su cvstart.org ora porta la versione del rilascio generatore, così il grader site-build-after-fanout esercita finalmente la sua vera logica invece di saltare.
  • Deliberatamente non fatto: il throttling dei POST mutanti rimanenti (review LOW №3) e l’accoppiamento trust-proxy dei bucket — annotati nel BACKLOG per la prossima onda di indurimento. CAR-141 (video dimostrativo) resta al proprietario.
  • Tests 7081 → 7082 (+1 pin CAR-219); Playwright 176; registro invariato: 123 = 118 EN + 5 RU · 118 adapters.

[1.264.1] — 2026-10-31

Corretto

  • Le pill del sidebar troncano con garbo le etichette localizzate lunghe (CAR-203) — lo span dell’etichetta di navigazione è ora un cittadino flex a tutti gli effetti (min-width: 0 + overflow: hidden + text-overflow: ellipsis + nowrap in v2-nav.css), e syncLabelTitles() in nav-v2.js rispecchia l’etichetta localizzata nel tooltip tramite la stessa chiave data-i18n (zero nuove chiavi i18n) — la lunga «Профинансированные компании» è di nuovo leggibile al passaggio del mouse invece di venire troncata di netto dall’overflow: hidden della riga. Il touch target di 44 px, la tinta attiva e il mirror RTL non sono toccati; pin red-first in tests/nav-v2.test.mjs.
  • Un solo soffitto di valutazione di 480 s per ogni località (CAR-218) — la remote-QA di v1.264.0 ha colto valutazioni transitorie 502 · 300 s · 0 ch su es e zh-CN (il re-run puntuale è passato, ma il muro era reale). EVAL_TIMEOUT_MS è ora 480_000 e evalTimeoutMs(lang) lo restituisce incondizionatamente — GEMINI_EVAL_TIMEOUT_MS e l’auto-pipeline lo ereditano. Il budget token sensibile alla località da CAR-174 (16384 / 32768) resta l’unica suddivisione per località.

Modificato

  • La FAQ di cvstart.org porta i conteggi esatti delle fonti (CAR-217) — il template {sources} job-board sources: {sourcesEn} international boards plus {sourcesRu} Russian ones è sostituito da facts.json, generato dal registro live (123 = 118 EN + 5 RU), così i numeri non possono mai andare in deriva; le località ancora sulla formulazione più vecchia ~{adapters} continuano ad arrotondare via adaptersRounded. Gli upgrade della copia EN viaggiano nello stesso giro (meta.helpDesc, helpTeaser.c1.desc, faq.a2 nominano la palette dei comandi, la pipeline raggruppata con undo e il tracker kanban).

Note

  • Deliberatamente non fatto: gli upgrade della copia i18n del sito (meta.helpDesc / helpTeaser.c1.desc / faq.a2) restano EN-only in questo rilascio — le altre località mantengono formulazioni corrette ma più arrotondate fino alla prossima onda documentale (il loro faq.a7 riceve i placeholder dei conteggi esatti dove è tradotto). CAR-141 (video dimostrativo) resta al proprietario; il ramo superato car136/m141 è stato eliminato con le sue idee annotate nella task Linear (recuperabile via tag archive/car136-m141).
  • Tests 7041 → 7081 (pin CAR-203 + pin CAR-218 riscritti); Playwright 176; registro invariato: 123 = 118 EN + 5 RU · 118 adapters.

[1.264.0] — 2026-10-31

Aggiunto

  • Modifica inline dello stato del tracker — il badge di stato di ogni riga di #/tracker è un <select> compatto degli stadi canonici (da GET /api/tracker/stages, mai una whitelist hardcoded). POST /api/tracker/status inoltra al set-status.mjs canonico del padre sotto il lock di applications.md (whitelist degli stati via states.mjs, pass-through di --dry-run/--note, 502 fail-soft con dettaglio sanificato, spawn con array argv). Il successo aggiorna la riga sul posto (classe di tono + conteggi delle schede, focus mantenuto); il fallimento ripristina e mostra un toast. Le righe che il relay non può indirizzare — uno stato sconosciuto modificato a mano, un sentinel di backfill # — mantengono il badge di sola lettura (fix LOW della route-review; revisore: nessun finding HIGH/MED).
  • Avvisi del server mostrati su ogni pagina IA — evaluate, deep, auto-pipeline (pagina e modal), career-plan, market, cv-studio (humanize + tailor) ora renderizzano l’array warnings del server (troncamento dei token di output, deriva linguistica, correzioni di data) come una fascia badge-warn (role="status"); la modal dell’auto-pipeline non scarta più gli avvisi del frame done. Nuova chiave llm.truncatedNotice ×19.
  • Onda di copertura (+111 test) — 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 (nuovi tests/cov-*-routes.test.mjs ×3, tests/sources-habr.test.mjs); pavimento dei rami tenuto a ≥ 90 %.
  • Pacchetto di chiusura Linear CAR-191…216 (docs/reviews/2026-10-30-linear-car191-216-closure-bundle.md) — chiusura per il proprietario pronta da incollare, con commit SHA per CAR e commenti di prova.

Corretto

  • Fonte di scan Trudvsem — una pagina vuota (results: {}, anche «oltre la fine») non uccide più l’intera scansione (zero righe pulite); le buste di errore dell’API (HTTP-200 con status: 500) lanciano con il testo dell’API stessa; la paginazione cammina sugli offset dei record (era l’indice di pagina — le pagine si duplicavano in silenzio, ~52 offerte invece di centinaia); la camminata si ferma prima della zona di fallimento dei deep-offset dell’API (offset × limit ≥ 10000). Verificato dal vivo end-to-end.
  • habr — titoli/aziende vengono ripuliti dai tag dopo la decodifica delle entity (parità con hh.mjs): &lt;script&gt; in un titolo di scheda non può più arrivare alle righe di scan come markup vivo; i >> legittimi nei titoli sopravvivono.
  • PUT /api/profile (percorso raw) — un blocco candidate: senza un full_name non vuoto viene rifiutato, stessa linea del percorso di merge dei campi (prima persisteva full_name: null).
  • Suggerimenti veritieri — .doc rimosso dalla lista di accettazione dell’upload del CV e da cv.uploadHint ×19 (il parser non l’ha mai supportato); config.openaiModelHint ×19 nomina gpt-5 (il server mappa qualsiasi id *-codex su di esso); config.anthropicModelHint ×19 e il default Anthropic ora rispecchiano i tier del padre — predefinito claude-sonnet-5-5, premium claude-opus-5-5.
  • Link ai documenti di Claude Code → code.claude.com (il vecchio URL docs.anthropic.com/en/docs/claude-code genera un TypeError nel gate dei link).
  • help ×19: il bullet sulla densità delle righe è sparito (il toggle ha lasciato la UI nella v1.263.0) e 18 famiglie di span in **grassetto** rotti sono riparate — più la classe di leak del renderer sistemata ×19 (seconda riga vuota dopo ogni tabella-prima-del-paragrafo; il glifo pipe fuori dalle celle in grassetto): 0 ** letterali nel rendering su tutti i 19 bundle della guida.

Note

  • Il modello predefinito di Anthropic è cambiato in claude-sonnet-5-5 (il tier standard del padre). I deploy che si affidavano al vecchio default silenzioso (claude-sonnet-4-6) si aggiornano automaticamente — fissare ANTHROPIC_MODEL in .env per rinunciare.
  • Deliberatamente non fatto: le due criticità LOW lasciate aperte di proposito (il select inline non rispecchia la degradazione movesReady del kanban — il toast onesto a ogni fallimento è il comportamento scelto; il ramo code: 'timeout' resta coperto dal contratto del fake-writer, non da un test >30 s). CAR-141 (video dimostrativo) resta al proprietario.
  • help ×19 ha ricevuto la passata di prosa post-release (bullet della densità fuori, classe di leak del renderer sistemata) su main dopo l’uscita della v1.263.0 — questa release è il primo tag che la porta.
  • Anche in questo tag: la base del chip di evidenza (parser dei report + badge della vista), il runner fix-report-links (POST /api/runners/report-links, card «Ripara» su #/health) e la stima/conferma del costo del batch con registrazione usage — arrivati su main tra il taglio del branch e il tag.

Tests 6905 → 7041 (+136) · Playwright 176 (173 superati / 1 skip opt-in) · copertura 98.5 % righe / 90.1 % rami · registro invariato: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.263.0] — 2026-10-30

Aggiunto

  • Strato di rifinitura del movimento — nuovo motion.css (ultimo foglio dell’app): entrate di modal/popover (scale .97 + dissolvenza, 130–180 ms), spring-in del toast + stato di uscita morbido, molla della pressione del theme-toggle, pressione chip/tab scale(.97), infrastruttura a scaglioni (passi da 50 ms, tetto 12), dissolvenza al cambio di rotta .page-enter (router), transizioni focus-halo su chip/tab. Ogni regola è sicura per prefers-reduced-motion (il movimento scende a none, opacità/colore restano).
  • Correttezza touch — 68 regole di hover-lift erano non protette: i dispositivi touch tenevano bloccata una carta “sollevata” dopo un tocco. Tutti gli hover con transform ora sono vincolati da @media (hover:hover) (neutralizzatore di motion.css), e il sollevamento della carta si applica solo alle carte genuinamente interattive (.card:has(a), a.card, button.card, [role=button].card) — niente più false affordance sulle carte statiche.
  • A11y: ogni controllo ha un nome programmatico. Il nuovo helper A11yDump nomina tutti i 16 dump di output LLM di sola lettura; 12 campi solo-placeholder (CV Studio ×6, config ×2, ricerca scan, select punteggio tracker, nota outcome, editor plan, URL auto, bug report) hanno ricevuto aria-label; il gate a11y-form-wires ora lo impone a livello di classe (prima 26 siti senza nome, ora 0 + allowlist con motivazioni documentate).

Corretto

  • #/scan: l’intestazione sticky della tabella non dipinge più sopra la ricerca della topbar quando questa scorre sotto di essa (z era pari a quello della topbar, il DOM successivo vinceva — ora derivato dai token sotto di essa); gli input «Зарплата от/до» sono di nuovo di dimensioni normali (una regola flex .v2-scan-bar .input trapelava nel flex di colonna del popover e impostava flex-basis 200 px come ALTEZZA — ora con scope > + guardia del popover); il pulsante di attivazione della densità è rimosso per decisione del proprietario (il cablaggio resta, chiavi i18n rimosse ×19).
  • Indurimento del workflow di deploy (F1–F6): input provider validato per charset prima di qualsiasi splice di shell; la diagnostica hermes oscura i valori (filtro delle chiavi case-insensitive + maschera del valore + taglio a 80 caratteri su tutti e tre i sink, ?token= mascherato anch’esso); il passaggio hermes rispetta inputs.app_dir; public_url vincolata a https; la guardia anti-downgrade ha 6 pin eseguibili (nessun default, ordine guardia-prima-di-Deploy, regex strict sui refs).
  • Coda delle revisioni, red-first: round-trip del backslash dell’import CSV (il re-import ha di nuovo deduplicato), head-strip di cv-voice 4827 ms → 13 ms, statedYearsMin calcolato con pigritizia, TOCTOU della cattura del posting-guard, wildcard CN di MiniMax, salto del token deel, guardie di dimensione del selettore di import prima della lettura. Modal di import: nav-guard armata, input file rimosso all’annullamento, letture di duplicati custodite, num via reduce.
  • Batch UX del proprietario: ritmo verticale dell’hero della dashboard (figli a livello inline incollati in una sola line box); spostamento di −8 px della riga attiva nel TOC della guida (gutter inline per riga + colonna numerica); drawer mobile (chiusura ✕ visibile, reset dello scrollTop, la dissolvenza fantasma --paper vincolata a .has-hud); la pagina docs-assistant non va più in overflow con un URL lungo in una risposta (catena min-width della griglia + overflow-wrap: anywhere); «Недавние» spiegato (suggerimento) + cancellabile; il Save di career-plan si riarma dopo un caricamento fallito; il prefill URL di evaluate non brucia più una chiamata LLM sul segnaposto dell’incolla; l’Enter dell’auto-pipeline rispetta la composizione IME.
  • Contrasto (audit WCAG, 296 coppie): gradiente del docs-fab 2.43 → 6.4:1, coppia toast.success → ok-soft (1.75 → AA dark), flip del banner btn-dark → --ink, varianti chiare di scan-logbtn/reposts-badge/fab-chip/close, e bordi dei controlli dei form a 3:1 (--cv3-input-line, WCAG 1.4.11 — era 1.2:1).
  • Spazzata visiva: lo stato vuoto del tracker è una carta a piena larghezza (era tagliato dentro la tabella di 760 px a 390); la riga della console di scan va in ellissi invece di tagliarsi a metà; il FAB della chat fluttuante non copre più il contenuto a 390 (obiettivo 44 px, inset 12); lo stato vuoto «Application statuses» della dashboard segue il pattern v2-empty; il suggerimento «?» delle statistiche ottiene un divisore + obiettivo 44 px; il tab Input di career-plan spiega dove atterra il risultato; markdown della guida §1 (18 span in grassetto rotti).

Modificato

  • Accento blu → rosso cremisi (richiesta del proprietario, coerente col logo, hue 15) — 5 token cv3 × 3 blocchi tema; il testo della bolla di chat di docs-assistant cavalca --accent-ink (era #fff letterale, 2.39:1 in dark); il lavaggio di funded cavalca --accent-soft. Il danger resta hue 25 con i suoi trattamenti propri.
  • Docs: conteggio della tabella testing del README ×17 (una deriva dell’era v1.248), guida §1 + 18 span markdown, guida fr/it/ta «118», prezzi dei fornitori CHECKED_ON 2026-10-30, fatti di HANDOFF/CONTEXT/TRACEABILITY.

Note

  • Deliberatamente non fatto: la rielaborazione della spazzata degli skeleton resta fuori (il contratto car112 blocca verbatim la dissolvenza attuale); il crossfade dell’icona del theme-toggle resta uno scambio display (il contratto Playwright del theme-toggle lo osserva); la scala .btn:active non è stata duplicata (app.css la possiede); lo scaglione del movimento è solo infrastruttura — le tile della dashboard lo adotteranno più tardi; la prosa della guida ×19 (menzione della densità, markdown §1, «118») viene con il prossimo fan-out.
  • Prove complete della remote-QA: spot di ja verde (376 s / A–G ✓) su v1.262.4; en/it verdi prima nell’era token-dense.

Tests 6869 → 6905 (+36) · Playwright 176 · copertura 98.4 % righe / 89.9 % rami · registro invariato: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.262.4] — 2026-10-30

Corretto

  • ja entra nelle località token-dense di valutazione (ja → il soffitto di 32768 token + l’orologio di 480 s). Il re-run puntuale a 5 località sul prod v1.262.3 ha separato i quattro timeout 502 · 300 s · 0 ch della notte in transitori e deterministici: ar (250 s), ko (291 s) e zh-CN (259 s) hanno passato i loro re-run, la deriva linguistica una tantum di ru non si è ripetuta — ma ja ha colpito il soffitto standard due volte con output zero (l’esecuzione completa ×19 40981578549 e quella puntuale 41012725839). Stessa classe di forma di it/pl. Pin red-first: evalMaxTokens('ja') = 32768, evalTimeoutMs('ja') = 480_000, le altre località mantengono 300 s.

Note

  • Deliberatamente una patch a scopo unico: la correzione di ja è l’unico cambio che questa versione porta — non porta nient’altro. ar/ko/zh-CN restano al soffitto standard sulle prove di stanotte (passano; i fallimenti della notte erano transitori da carico del provider), e la deriva di ru è stata un’anomalia di generazione una tantum.

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

[1.262.3] — 2026-10-30

Corretto

  • pl entra nelle località token-dense di valutazione (pl → il soffitto di 32768 token + l’orologio di 480 s). La remote-QA completa sul prod v1.262.1 ha colto la valutazione polacca mentre moriva al soffitto standard — 502 · openrouter · 300 s · 0 ch — e il re-run puntuale inviato con v1.262.2 l’ha riprodotta esattamente (le esecuzioni 40960568766 e 40968958062): 18/19 località hanno passato A–G, it è finita a 302 s entro l’orologio token-dense di 480 s, e pl ha colpito il muro due volte con output zero. Un timeout deterministico, non un’anomalia — la stessa classe di forma che ha mosso it in v1.262.1. Pin red-first: evalMaxTokens('pl') = 32768, evalTimeoutMs('pl') = 480_000, le 18 località standard mantengono 300 s.

Note

  • Deliberatamente una patch a scopo unico: la correzione di pl è l’unico cambio che questa versione porta — non porta nient’altro; il contenuto della coda della revisione di v1.262.2 è uscito separatamente.

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

[1.262.2] — 2026-10-30

Corretto

  • Coda della revisione d’ondata — 7 reperti di bassa gravità, ciascuno chiuso red-first. Il round-trip del backslash dell’import CSV: un \ in una cella veniva scritto raddoppiato e riletto raddoppiato, così il re-import dello stesso CSV saltava il dedup azienda+ruolo e poteva creare una riga duplicata — il lettore ora fa l’unescape di \\ dopo lo split (il round-trip scrittura→lettura è senza perdite, il re-import deduplica). Lo strip <head> di cv-voice era quadratico sui tag non chiusi — 4827 ms → 13 ms sull’input da 64 KB che la rotta pone a tetto. statedYearsMin eseguiva il parser completo degli anni per ogni posizione di ogni fonte anche quando years_min non era configurato — ora è lazy, i secondi di CPU per scan estesi sono spariti. Una capture cancellata tra readdir e statSync faceva crashare l’elenco del posting-guard (TOCTOU — i file scomparsi vengono saltati). Il predefinito MiniMax CN combaciava solo con api.minimax.cn esatto — ora qualsiasi URL di base *.minimax.cn riceve il modello CN. I token $ di Deel che non sono riferimenti hex non filtrano più nello snippet come letterali. L’import picker controlla file.size PRIMA di file.text() — il tetto server di 512 KB rispondeva 413 solo dopo che il browser aveva analizzato un file potenzialmente enorme — con un toast import.tooLarge localizzato ×19.
  • Indurimento del workflow di deploy (revisione dei workflows F1–F6). provider era l’unico input interpolato nella shell remota senza validazione del charset — un ' nel valore rompeva il quoting ed eseguiva codice arbitrario in produzione; ora è in whitelist ^[A-Za-z0-9_-]+$ prima di qualunque splice, e la grep della guardia della chiave non può più passare per falso positivo. Il passo diagnostico hermes stampava journalctl grezzo + dump delle unit nel log pubblico; il suo filtro ignorava *_API_KEY= in maiuscolo e non mascherava nulla — ora un redact condiviso case-insensitive + mascheramento dei valori + troncamento a 80 caratteri su tutti e tre i sink, e anche le query string ?token= sono mascherate. Il passo hermes ignorava inputs.app_dir e aveva hardcoded /opt/career-ops/src/.env. public_url arrivava a curl senza un controllo https (iniezione di opzioni tramite un - iniziale). E la guardia anti-downgrade — la correzione dell’incidente v1.238.0 — non aveva un gate eseguibile: sei nuovi pin in ci-workflows (i ref non hanno default, la guardia gira prima di Deploy, regex dei ref severa).
  • Coda della import-modal (revisione SPA). La modale arma la stessa nav guard della modale outcome — navigare altrove non la lascia più orfana sopra un’altra vista. L’input file nascosto viene rimosso su cancel, non solo su change — le chiusure ripetute non infiltrano più input in document.body. plan.duplicates viene letto nella forma guardata nell’anteprima. L’allocazione di num del tracker usa reduce invece di Math.max(...spread) — lo spread raggiunge il limite degli argomenti a ~100k righe.

Modificato

  • Docs: il bullet «118 EN adapters» della guida ora riporta il conteggio in fr/it/ta (le altre 15 località lo avevano già). I prezzi dei vendor su cvstart.org riverificati contro le pagine prezzi ufficiali — tutti e quattro invariati, CHECKED_ON → 2026-10-30. Una sweep post-rilascio delle derive ha corretto 42 righe conteggio/versione stantie in README ×19, CONTEXT.md, CLAUDE.md e i manuali SDD (residui dell’era 109/104 e dell’era v1.262.0).

Note

  • Non-azione deliberata: il nativo window.confirm di cv-studio (era CAR-179) resta — convertirlo a UI.confirm è un lavoro a seguire, non un punto della patch; il tooltip delle frasi fatte <mark title> resta solo tooltip (pavimento di a11y accettabile); remote-qa.yml mantiene cancel-in-progress: true — il ri-dispatch sostituisce intenzionalmente una regressione in corso.
  • Remote-QA completa sul prod v1.262.1: rotte ×19 ✓ · sito ×19 ✓ · link ✓ · LLM live 18/19 località A–G ✓ — pl ha colto un singolo timeout del provider 502 · 300 s · 0 ch (non territorio token-dense; il re-run puntuale viaggia con questo rilascio).
  • Test 6841 → 6867 sul ramo di rilascio (6864 pass / 0 fail / 3 skip, +26) · Playwright 176 · copertura 98.42 % righe / 89.94 % rami · registro invariato: 123 sources = 118 EN + 5 RU · 118 adapters.

[1.262.1] — 2026-10-29

La patch della valutazione italiana: it entra nelle località token-dense (soffitto di 32 768 token + orologio di 480 s) dopo che l’era OpenRouter l’ha colta a tagliare il report subito prima del blocco SCORE_SUMMARY — e lo strumento di cambio provider che ha reso possibile la diagnosi arriva nel workflow di deploy.

Corretto

  • Valutazione it tagliata prima di SCORE_SUMMARY (coda CAR-190): remote-QA 40928864980 (prima esecuzione con i crediti ricaricati) — una valutazione it è durata 264 s ed è tornata con 15 045 caratteri, tok ~15635 al soffitto di 16 384: blocchi A–G intatti, ---SCORE_SUMMARY--- sparito. La stessa classe di forma che è valsa a ta il suo soffitto in v1.261.1 (CAR-174). it entra in TOKEN_DENSE_EVAL_LOCALES (ta, hi → ta, hi, it): valgono ora sia il budget di 32 768 token sia l’orologio di 480 s, e /api/evaluate + auto-pipeline restano sull’unica fonte di verità in llm.mjs.
  • Report en senza blocchi — un’anomalia di generazione isolata: la stessa esecuzione ha visto una singola valutazione en tornare linguisticamente corretta ma senza nessuno dei blocchi A–G; una riesecuzione mirata è passata pulita (21 091 caratteri, A–G ✓). Non aggiunto all’insieme token-dense — un’anomalia isolata non è una storia.

Aggiunto

  • Workflow di deploy: mode=hermes e mode=provider (coda ops CAR-190): mode=hermes riavvia il gateway Hermes e stampa una diagnosi completa (unit file con i segreti rimossi, listener prima/dopo, journal sudo, sonde porta per porta, la vista HERMES_BASE_URL dell’app stessa, saldo dei crediti OpenRouter); mode=provider cambia LLM_PROVIDER con una guardia di presenza della chiave (rifiuta quando manca la *_API_KEY del provider di destinazione) e riavvia l’app — è così che la produzione è passata a openrouter quando i crediti Hermes si sono esauriti in corsa. La guardia del ref delle modalità di deploy è validata solo per mode=deploy, quindi i dispatch di recon/verify funzionano di nuovo (la modifica required-inputs dell’era v1.261.3 li aveva silenziati).

Note

  • Non-azione deliberata: en non entra nell’insieme token-dense — un report senza blocchi è un’anomalia di generazione, non una storia di volumi.
  • Non-azione deliberata: la direttiva linguistica rafforzata per ta non si estende a it — nessuna deriva linguistica osservata per l’italiano.
  • Non-azione deliberata: la registrazione del nuovo video dimostrativo UI-v2 resta al proprietario (CAR-141) — la landing ora incorpora comunque via youtube-nocookie.com.
  • Test 6841 → 6841 sul ramo di rilascio.

[1.262.0] — 2026-10-29

Il minor delle funzionalità upstream: il board Deel entra nello scanner (registro 123), il CSV di un tracker estraneo si importa direttamente in #/tracker, il controllo di integrità posting-guard e il controllo voce del CV arrivano come relay/lint, lo scanner impara un filtro anni-di-esperienza, e i pulsanti Apply in altre sette lingue non risultano più mancanti — più il modello predefinito ritirato di MiniMax viene sostituito e i repost non vengono più fabbricati tra le fonti.

Aggiunto

  • Fonte board Deel (CAR-184): registro 123 fonti = 118 EN + 5 RU · 118 adapter — rileva automaticamente i board tenant jobs.deel.com/<slug> (Klarna e altri); il payload flight di Next.js porta l’intero inventario in una sola richiesta (titoli, sedi, modalità, date, descrizione), il percorso /api/ non consentito non viene mai toccato, un tenant che pubblica le posizioni altrove risponde con un redirect che la fonte rifiuta per nome, e la retribuzione resta deliberatamente non mappata (importi senza intervallo di pagamento sarebbero un indovinello); count gate ×5 + guida §17 ×19.
  • Import CSV tracker (CAR-181): POST /api/tracker/import-csv con anteprima dry-run e commit bloccato — quoting RFC-4180, date in forme ISO / giorno-prima / nome-mese, fasi di tracker estranei ripiegate sugli stati canonici (una fase sconosciuta approda come Evaluated con una nota, mai scartata), dedup per URL di pubblicazione normalizzato letto dalla cella markdown-link o dalla colonna Note, limiti 512 KB / 2000 righe; #/tracker guadagna un pulsante Importa CSV con modale di anteprima, i18n ×19.
  • Relay posting-guard (CAR-182): POST /api/runners/posting-guard — il gate deterministico zero-LLM di integrità JD del parent, risolto per numero di report tramite la regola di prefisso delle capture jds/ (con o senza padding, confronto per intero) o un percorso esplicito sanificato; il figlio riceve solo argv, un tetto di 30 s e un contratto fail-soft; un’azione «Posting guard» su #/reports/:slug mostra i reperti, i18n ×19.
  • Controllo voce CV (CAR-188): 27 frasi fatte da curricula (passionate about, proven track record, leveraged, spearheaded, delve…) più euristiche sul trattino (un intervallo di anni come 2022–2024 non è un indizio; 20–30% lo è) come POST /api/cv-studio/voice-check di sola lettura e una card #/cv-studio che evidenzia le corrispondenze esatte; la checklist del Tailor cresce a sei invarianti; i18n ×19.
  • Filtro scan anni-di-esperienza (CAR-180): il parser jd-years (65 formulazioni, non scarta mai se non è sicuro) legge il minimo dichiarato dalle descrizioni delle posizioni, una nuova opzione years_min: di portals salta le posizioni sottoqualificate come skipped_experience (uno stato osservativo della cronologia che non blocca mai un URL), e yearsMin viaggia nello snapshot dello scan per una futura UI.
  • Controlli Apply in altre sette lingue (CAR-185/189): vietnamita Nộp đơn ứng tuyển, bulgaro Кандидатствай/Кандидатстване/Външно кандидатстване (il sostantivo ancorato all’inizio dell’etichetta — i link ad articoli di consigli non sono Apply), olandese Solliciteer/Solliciteren, spagnolo ¡Apúntame!/Postularse (etichette, non il verbo — i link FAQ non contano più), cinese 申请职位/投递 (ancorato all’intero controllo) — le pubblicazioni attive su quei board non leggono più no_apply_control.

Corretto

  • Modello predefinito MiniMax (CAR-187): il predefinito ritirato MiniMax-Text-01 è sostituito da MiniMax-M3.1-Flash su api.minimax.io e MiniMax-M3 su api.minimax.cn; l’URL di base è bloccato sul vendor (un host non-vendor viene rifiutato a runtime e la chiave non lo raggiunge mai); l’hint delle impostazioni ×19 nomina i nuovi predefiniti.
  • I repost richiedono la stessa fonte (CAR-186): un ruolo elencato su LinkedIn e sul Greenhouse del datore di lavoro non viene più riportato come repost — i cluster ora si dividono per sourceHost(), che ripiega i sottodomini regionali solo su siti noti (de.linkedin.com ≡ www.linkedin.com, ma ca.example.com resta separato), ripiega gli alias host Greenhouse in un’unica fonte e rimuove un punto finale.
  • Deriva linguistica delle valutazioni tamil (CAR-183): una direttiva tamil rinforzata ora siede nella coda volatile del prompt accanto al budget di volume (lo slot CAR-174) — i report remote-QA tornano in tamil dopo la deriva intermittente vista in v1.261.2.

Note

  • Non-azione deliberata: il relay posting-guard viene rilasciato fail-soft — il fork non porta ancora posting-guard.mjs del parent (la PR upstream #6146 è ancora aperta), quindi l’endpoint risponde {available:false, reason:"script-not-found"} finché una sincronizzazione del parent non lo spedisce.
  • Non-azione deliberata: yearsMin non viene esposto come chip UI di #/scan in questa release — il campo viaggia nello snapshot e il filtro è solo config-di-portals.
  • Non-azione deliberata: le modifiche Machine Summary upstream di modes/reports (#6161/#6160/#6157) non sono portate — arrivano con il parent distribuito, non come mirror web-ui.
  • Test 6734 → 6841 sul ramo di rilascio; la chiave di dedup dello scanner è intoccata (il comportamento di normalizzazione degli URL non è cambiato).

[1.261.3] — 2026-10-28

La patch di completamento del design: la fase 3 del design Lovable (densità + ritiro completo del corallo), il pool di host dello scan (32 aziende, 10 per host), cinque fix di localizzazione dei provider upstream, la fonte Trakstar Hire (registro 122), l’undo + la guardia unsaved di CV Studio — più i fix P3 della regressione finale e la parità della documentazione.

Corretto

  • Etichetta «related» dei cluster della mappa 3.16:1 → 4.68:1 (entrambi i temi): il --map-score-mid chiaro è stato scurito a #567b75 (il #5f7f7a suggerito misurava solo 4.37 — serviva un passo in più); il lato dark era già a 4.98:1, intoccato. Pin rosso-first in map-cluster-visual.
  • Anello di focus dello skip-link: l’ultimo outline letterale #ff385c → var(--accent-c) — tutti i 78 anelli di focus seguono ora il token dell’accento.
  • Topologia dell’accento di .tab-btn.is-active (#584, fase 3): il controllo mescolava tre famiglie di colore (lavaggio corallo + testo danger + bordo blu); ora un’unica coppia accent-soft.
  • Fix di localizzazione dei provider upstream ×5 (#580, CAR-176): flag workday Fully Remote (non è un luogo), fan-out telecommuting workable + stato solo in assenza di città, virgola finale successfactors, word-boundary remote lever, etichette con prefisso Location icims.
  • http-json: nessun retry su un timeout esaurito (#580) — un abort di scadenza è non transitorio in entrambi gli helper di retry (l’upstream ha misurato ~94s su un board Ashby a 30s×retry).
  • Parità della documentazione (#587): gli ultimi contatori dell’era 17/18 in HANDOFF/CONVENTIONS/README (uk riceve la sua sezione Локалізація mancante; la storia dei § estesa a §32/§33 — aritmetica dei 33 H2 verificata).

Aggiunto

  • Fase 3 del design Lovable (#584): i token di densità sono attivi — righe di tabella ≈32px, controlli 30px, chip 24px (eccezione di spaziatura WCAG 2.5.8); ogni residuo rgba corallo spostato sulle coppie cv3 (.dash-hero, .badge-bad, aloni, .tab-btn.is-active); --ease-out dichiarato, TOKEN_HANDOFF vuoto; contratto .callout--ok/--danger.
  • Fonte Trakstar Hire (#583, CAR-177): registro 122 fonti = 117 EN + 5 RU · 117 adattatori — host-pinned jsapi.recruiterbox.com, percorso a offset con arresti brevi/vuoti/ripetuti, parziali conservati, marcatura trakstarTruncated; gate di conteggio ×5 + guida §17 ×19.
  • Pool di host dello scan (#579, CAR-178): fino a 32 aziende in concorrenza, con tetto di 10 per host (pattern keyed-limiter upstream) — snapshot byte-per-byte identico all’esecuzione sequenziale (gate timing-mock rosso-first).
  • Undo + guardia unsaved di CV Studio (#582, CAR-179): stack di undo limitato (30) sui risultati delle esecuzioni AI con Cmd/Ctrl+Z sicuro per tastiere non-QWERTY, guardia unsaved-changes all’abbandono della rotta (probe live del dirty, confirm/rewind/beforeunload), i18n ×19.
  • Fix dei provider upstream testati ×17 (parte di CAR-176); il sommario della remote-QA nomina le fonti di scan in fallimento + tok ~N per valutazione (#567, già in v1.261.2 — l’osservabilità è stata usata per il triage di questa release).

Note

  • L’accento ora è blu (concetto Lovable): azioni primarie/stati attivi/anelli di focus seguono --cv3-accent; il rosso è riservato al danger (.btn-danger, toast.error, testo di danger). Il corallo sopravvive solo nell’asset PNG del logo (decisione del proprietario).
  • Densità: righe di tabella ≈32px / controlli 30px / chip 24px — eccezione di spaziatura WCAG 2.5.8 documentata; il canary 44px della v1.26.1 è stato riscritto sul contratto dei token.
  • CodeQL: tutti i 10 alert aperti sono chiusi (4 archiviati come falsi positivi con motivazione: classi documentate llmRateLimit/atomicWrite; 6 corretti alla fonte).
  • Test 6655 → 6734 sul branch di release; nessun comportamento delle fonti di scan cambiato oltre la nuova fonte Trakstar.

[1.261.2] — 2026-10-28

La patch di stabilità e rifinitura: la cache del geocoding sopravvive a un crash a metà scrittura (CAR-173), UI.md renderizza le continuazioni dei bullet e gli elenchi annidati, le fughe di chiavi nel testo renderizzato dei bundle della guida sono chiuse ×17, le valutazioni ottengono un tetto di token per locale per il ta (CAR-174), il chrome RTL va in specchio tramite proprietà logiche (85 finding), le catture della mappa sono ri-inquadrate ×19 e i cluster della mappa passano il contrasto in dark — più la prima fase dell’integrazione del design Lovable (foglio passivo tokens-v3.css), il backfill della documentazione (release review + specifiche) e le esenzioni di copertura per la varianza dei nodi CI.

Corretto

  • Perdita per scrittura strappata della cache del geocoding (CAR-173, #562): entrambi i percorsi di flush (insert-flush con debounce, exit-flush) scrivevano .cache/geocode.json con un writeFileSync nudo — truncate-then-write — così un crash, un OOM o un SIGKILL a metà scrittura lasciava un file strappato e il JSON.parse del boot successivo falliva, scartando in silenzio l’intera cache persistente (settimane di budget Nominatim), non solo quella del giorno. Entrambi i siti di scrittura ora passano per file-lock.mjs::atomicWrite (temporaneo nella stessa directory → rename → unlink al fallimento) — lo stesso contratto che FULL-R1/FULL-M1 hanno applicato a pipeline.md, cv.md, profile.yml, career-plan, all’input del batch e alla memoria. La macchina di flush di CAR-142 in sé (insert-flush con debounce, exit-flush, shutdown limitato) è stata verificata intatta red-first: i test (a)/(b) vincolano che gli insert raggiungano il file entro la finestra GEOCODE_SAVE_MS e che resti JSON valido; (c) è un gate di meccanismo più esecuzioni comportamentali di entrambi i percorsi di flush che asseriscono nessun residuo di temporanei e un file interpretabile.
  • Continuazione degli elenchi in UI.md (#563): l’handler degli elenchi consumava solo righe consecutive - /* , così una riga di continuazione indentata dopo un bullet usciva dal <ul> emesso e il passaggio dei paragrafi saltava il chunk — la continuazione finiva come prosa grezza con marcatori **/backtick letterali (~95 frammenti orfani per locale attraverso i bundle della guida; en.md 95, ru.md 104). Una riga di continuazione — whitespace iniziale, non un nuovo blocco (heading, bullet, placeholder di fence avvolto in NUL, riga vuota) — ora si unisce al <li> precedente come testo concatenato da <br/>, con inline() eseguito riga per riga così i marcatori di enfasi non si accoppiano mai attraverso la giunzione; la guardia del placeholder di fence guarda il primo carattere NUL, non un match di token nudo. I bullet - annidati, gli elenchi numerati, i fence dentro gli elenchi e i heading dentro gli elenchi restano una lacuna documentata separata (prossima onda docs).
  • Fughe di chiavi nel testo renderizzato della guida ×17 (#561): la remote-QA ha trovato 85 chiavi i18n grezze visibili nella guida renderizzata (causa radice provata per riproduzione: lo stesso consumo del bullet a riga singola di UI.md — una continuazione andata a capo emessa come testo grezzo teneva i backtick letterali; le sezioni della guida v1.260/261 scrivevano bullet multilinea). 163 bullet riportati su una riga attraverso 17 locale — solo whitespace, non una sola parola tradotta toccata (verificato vecchio-contro-nuovo). Il nuovo gate tests/help-rendered-keys.test.mjs renderizza ogni bundle attraverso la catena reale (stripGithubOnlyBlocks + UI.md caricata in vm) e fallisce se qualunque delle 1.711 chiavi compare nel testo; red-first 17 locale → verde. Il tooling di riproduzione viaggia nel repo: scripts/remote-qa/help-render-scan.mjs (vm) + help-render-crosscheck.mjs (DOM reale).
  • La remote-QA asserisce il contratto della palette di CAR-122 per Ctrl+K (#561): prod-regression.mjs ora si aspetta la palette dei comandi dopo Ctrl+K (.nav-v2-palette[role=dialog] + focus su nav-v2-input) O il focus legacy sulla ricerca come fallback, invece di accettare in silenzio l’uno o l’altro; il test unitario tests/remote-qa-ctrl-k.test.mjs vincola 6 scenari su un DOM mock, red-first 0/6 → 6/6.
  • Inquadratura delle catture della mappa ×19 (#560): segnalazione del proprietario su images/job-map-en.png — metà della ricerca della topbar + un h1 tagliato in alto, una striscia grigia dell’elenco laterale sul bordo destro, un cluster di marker tagliato dal riquadro vicino a Londra e una linea orizzontale bianca attraverso la mappa a ~2/3 dell’altezza. capture-map-screenshots.mjs ora attende lo svuotamento della coda del geocoding (located + noLoc === total, non il contatore N/N — le righe Remote sono strutturalmente senza località, quindi la vecchia attesa non poteva mai completarsi), nasconde header.topbar e #notif-drawer per lo scatto, ritaglia l’esatto box .job-map-page (nessun pannello tagliato dal bordo del riquadro), riduce lo zoom di due passi così nessun cluster resta dimezzato, fissa l’altezza della mappa e prende uno screenshot semplice del viewport (captureBeyondViewport ricampiona il layer di tile composito e dipinge strisce bianche ai confini delle righe di tile) e allinea su valori interi il contenitore della mappa. Tutte le 19 catture del job-map ri-scattate.
  • Bolle dei cluster della mappa — contrasto nel tema dark e aderenza dell’etichetta (#572): sweep del proprietario P2/P3 — gli anelli dei cluster nel tema dark sedevano su un riempimento bianco fisso (1.83:1); ora gli anelli prendono var(--paper) con cifre della palette dei punteggi (misurato 4.98:1+, con riempimento 9.53:1; la fascia più bassa è matematicamente non colorabile su dark e mantiene 6.1:1 tramite un onesto percorso data-dim), e l’etichetta related sta nella sua bolla (font-fit via rAF, i numeri non si rimpiccioliscono mai).
  • #/scan cambio lingua — re-arm degli skeleton (follow-up di #534, agente in volo, atterra prima del tag): seguito del fix del proprietario della v1.261.0 (#534) — gli skeleton ri-armati su un repaint da cambio lingua non sopravvivono più a un refetch completato.
  • Deriva della documentazione (CAR-139, agente in volo, atterra prima del tag): contatori dei README ×19, HANDOFF ×19, fatti dei CONVENTIONS risincronizzati con lo stato live del registro e dei test.

Aggiunto

  • Release review + backfill delle specifiche (docs, #559/#558): docs/reviews/REVIEW-2026-10-28-v1.261.1.md (l’onda v1.261.0/v1.261.1 revisionata contro le sue specifiche) e il backfill delle specifiche SDD per la stessa onda — la coda del BACKLOG ora nomina la lacuna rimanente (test dedicati per sources/habr.mjs).
  • Sweep profondo RTL (#571): l’harness AR percorre 39 rotte × LTR-vs-RTL (specchio orizzontale, overflow, clipping, firme di text-align) — 85 finding corretti: il chrome fisso (toast, sidebar, drawer + la sua × di chiusura, docs-FAB, usage-HUD, skip-link) spostato su inset-inline-*/border-inline-*, le tabelle su text-align: start/end attraverso 17 file di viste + 2 librerie, la regola generica [dir=rtl] text-align:right rimossa (litigava con il centraggio della colonna a stelle della scan), l’isolamento della colonna punteggio di CAR-58 spostato su uno span ltrNum.
  • Harness di a11y da tastiera (#570): tests/playwright-a11y-keyboard.mjs percorre 11 rotte (ordine/trappole del Tab, indicatori di focus, overlay con Escape, Enter/Space) — 0 difetti di produzione; la copertura di regressione è nuova.
  • Sweep i18n dei non tradotti (#565): 36 valori identici all’inglese tradotti ×9 locale (*.rolePh, chiavi di config, manifesto ta) + una guardia di sweep a allowlist chiusa; audit i18n del sito (cvstart.org) (#568): 20 chiavi × 18 locale tradotte (l’intero blocco demo.*/stats.t.*/showcase.tab* era inglese ovunque), 1 chiave morta rimossa ×19.
  • Osservabilità della remote-QA (CAR-175, #567): il sommario nomina le fonti di scan in fallimento (campioni di stderr, redazione-prima-del-troncamento) e stampa tok ~N dall’uso dei provider; la logica vive in un puro summary-parts.mjs con un gate di deriva.
  • Elenchi annidati con marcatore in UI.md (un livello, #564): i bullet - renderizzano come un <ul> annidato (sicuro rispetto ai placeholder di fence) — gli ultimi 2 frammenti orfani di prosa per locale sono spariti.
  • Integrazione del design Lovable — fase 1 (#566) / fase 2 (branch, atterra prima del tag): public/css/tokens-v3.css riporta il concetto Lovable alla lettera (superfici oklch 0–3, coppie di inchiostro annotate AA, famiglia dell’accento, soft+ink per ok/warn/danger/info/neutral, fasce di punteggio A–G ×2 temi, densità + focus + ombre); la fase 2 lo attiva sui nomi dei token esistenti (accento diviso blue/danger, fasce di punteggio + callout sui token cv3) con i gate contrasto/ruolo/dark aggiornati.
  • Tetto di token per locale nelle valutazioni (CAR-174, #569): evalMaxTokens(lang) — ta/hi chiedono 32768 (i tre client SDK ri-limitavano a 16384; entrambi i livelli corretti), più un budget di volume tamil nel prompt (≤5 frasi per blocco, ≤900 parole) — il report ta della remote-QA della v1.261.1 era troncato al limite di token in uscita (mancavano i blocchi B–G + SCORE_SUMMARY).
  • Completamento dei fix reali di CodeQL: il nuovo tooling di render della QA ha sostituito la gestione a mano delle entità con passaggi di split strutturali + htmlToText({cap: Infinity}); le asserzioni di redazione vincolano l’esatto output mascherato; costanti inutilizzate dell’harness RTL eliminate.
  • Politica di esenzione della copertura per la varianza dei nodi CI (habr #558, states #561): sources/habr.mjs (branch in CI sulla matrice di nodi 87.23 vs locale ≥89) e states.mjs (CI 86.49 vs locale ≥89) entrano nelle esenzioni di scripts/coverage-baseline.json — i file la cui copertura di branch misurata in CI è strutturalmente sotto la soglia locale per via della varianza di versione di node vengono esentati invece di abbassare l’intero gate.

Note

  • Contratto Ctrl+K (CAR-122): il chord apre la palette dei comandi — NON mette a fuoco direttamente il box di ricerca; la ricerca viene messa a fuoco dalla palette. La regressione di produzione della remote-QA ora asserisce esattamente questo (#561).
  • Archiviazione dei falsi positivi di CodeQL ×5: gli alert js/missing-rate-limiting sul main attendono il token security_events — azione dell’operatore, non una modifica di codice.
  • Atterrati dopo il taglio del branch: #561/#562/#563/#564/#565/#566/#567/#569/#570/#571/#572 sono tutti uniti al main; gli agenti skeleton-di-#534 e CAR-139 si fondono prima del tag. Gli elenchi con marcatore annidati oltre un livello e la geometria delle viste ricca di inline restano lacune documentate.
  • Test 6609 sul branch di rilascio (+15 dalla v1.261.1; ~13 in più da #561 alla fusione — 2 nuovi file di gate); gli unici test rossi prima del fan-out sono i gate di parità del CHANGELOG ×19 (il fan-out delle locale è il passo successivo dell’orchestratore); nessuna fonte scanner toccata (registro 121 = 116 EN + 5 RU · 116 adattatori).

[1.261.1] — 2026-10-28

La patch client del QA di produzione: un fix di crash P1 per #/two-pager, Ctrl+K funzionante sui layout non-QWERTY, l’onda mobile da 390px (overflow del docs-assistant, sovrapposizione dei chip della mappa, un harness da 39 rotte), il completamento di CAR-137 (errori specifici, v2empty ×5, hint ×13 + mode-page) e CAR-140 che fa atterrare screenshot v2 reali ovunque.

Corretto

  • TDZ del two-pager (CAR-170, P1, #554): Cannot access 'previewTimer' before initialization — l’editor dei tag salvati sparava onChange durante la costruzione per ogni chip ripristinata mentre il loop di costruzione si trovava lessicalmente sopra let previewTimer, così l’intero render di #/two-pager andava in crash (nessun h1, ×19 locale). Scheduler e binding ora vivono sopra il loop; un test comportamentale esegue il modulo reale della vista — l’esatto errore di produzione prima del fix, una pagina renderizzata dopo — più un gate di deriva sull’ordine lessicale.
  • Ctrl+K sui layout non-QWERTY (CAR-172, #554): entrambi gli handler dei chord combaciavano solo su e.key — su un layout russo il chord arriva come key='л' code='KeyK' e non faceva nulla. Il match ora avviene su e.code === 'KeyK' in nav-v2.js e app.js; riprodotto in un browser reale con un chord sintetico ‘л’/KeyK. Il contratto di CAR-122 è riformulato (vedi Note).
  • Overflow del docs-assistant a 390px (CAR-172, #554): i chip iniziali di CAR-136 erano .btn (nowrap, flex-shrink: 0) — un elemento infrangibile da 418px spingeva #/docs-assistant 56px oltre un viewport di 390px; il pattern di shrink di CAR-146 (in v2-llm.css, i gate CSS sugli 800-LOC intatti) lo riporta a 0.
  • Sovrapposizione dei chip della mappa @390 (#552): su un viewport di 390px i chip meta della mappa si sovrapponevano alla riga CTA (map.css).
  • CAR-137 — errori specifici + v2empty ×5 (#550): cinque fallback di errore generici (‘Error’ / ‘failed’) sono diventati chiavi specifiche e azionabili — fallimento del POST di evaluate, stream dell’auto-pipeline senza un evento terminale, aggiunta a pipeline dalla scan, caricamento dei cluster di repost, undo della pipeline; gli ultimi cinque empty state piatti (#/reports, #/usage, #/portals, #/activity, #/dashboard) si uniscono al pattern v2empty di CAR-124 (spiegazione + esempio taggato aria-hidden + azione pre-cablata; 15 nuove chiavi v2empty.*, quattro chiavi morte di una sola riga rimosse) — tutto ×19 dizionari, snapshot rigenerato.
  • CAR-137 — HelpHint ×13 + kit delle mode-page (#550): l’hint contestuale «?» ora siede sull’H1 di ogni pagina rimanente (pipeline, reports, dashboard, cv, portals, usage, activity, assessments, map, health, docs-assistant, settings) e sulle 8 mode-page tramite il kit (ogni cfg MODES porta una hintKey, renderizzata tramite HelpHint.title).

Aggiunto

  • Harness mobile-390 (#552): uno sweep Playwright di ogni rotta SPA (31 canoniche + 8 mode-page = 39 hash) a 390×844 con un corpus seminato — controllo dell’overflow orizzontale per rotta (scrollWidth vs clientWidth, tolleranza di 1px, nomina il reo più largo) più un controllo di hit della CTA (nessuna barra sticky/drawer/FAB copre una CTA primaria); opt-in, skip pulito senza binario del browser, senza rete.
  • Nuovi screenshot v2 ×48 (CAR-140 fase A, #551): screenshot reali della UI v2 da un fixture CI-isolato e seminato — dashboard ×19 + job-map ×19 (job-map-ta alla prima comparsa, job-map-vi nuovo) + scan/pipeline/tracker/reports × en/ru — che alimentano README, guida e landing.
  • Screenshot reali su cvstart.org (CAR-140 fase B, #553): gli slot segnaposto di CAR-140 sono spariti — la landing mostra i veri screenshot v2 (showcase del job-map + righe di screenshot, ×19 locale della landing).
  • Hint di CAR-137 (#550): 21 nuove chiavi tradotte ×19 (help.hint.* ×20 + le hintKey delle mode-page) — ogni pagina ora si spiega sul posto.

Note

  • Contratto Ctrl+K (CAR-122): il chord apre la palette dei comandi — NON mette a fuoco direttamente il box di ricerca; la ricerca viene messa a fuoco dalla palette. La riga della checklist QA della v1.261.0 «Ctrl+K фокусит поиск» è superata; il prompt QA della v1.261.1 porta il controllo aggiornato.
  • Fix reali di CodeQL (#547): 4 alert chiusi (l’iterazione a chiavi letterali di content.mjs resa strutturale, sweep di lint) — atterrati post-release sul main della v1.261.0 prima di questa patch; elencati qui per completezza.
  • Test 6582 (+51); suite browser 171–172 pass / 0 falliti / 1 skip opt-in; l’harness mobile-390 gira in autonomia (node tests/playwright-mobile-390.mjs). Nessuna fonte scanner toccata (registro 121 = 116 EN + 5 RU · 116 adattatori).

[1.261.0] — 2026-10-28

L’onda della revisione completa della v1.261.0 è chiusa (tutti i finding HIGH + MEDIUM atterrati), il fix del cambio lingua segnalato dal proprietario, fix di qualità delle valutazioni, fan-out della guida ×18, la landing v2 di cvstart.org — più 4 specifiche SDD/OpenSpec che documentano l’onda. Ogni fix è atterrato tramite un fix-forward rosso→verde e una revisione GLM-5.3-Flash a contesto fresco.

Sicurezza

  • FULL-R1 — gate CSRF sugli acting-GET + scritture della pipeline atomiche e sotto lock (#519): gate Sec-Fetch-Site/Origin/Referer su /api/stream/*, /api/run/*, /api/geocode (ACTING_GET esportato, gate statico di copertura); ogni lettura-modifica-scrittura di data/pipeline.md / data/last-scan.json sotto withFileLock + il nuovo atomicWrite (temporaneo nella stessa directory → rename → unlink al fallimento).
  • FULL-R2 — cluster SSRF nelle fonti (#514): rss.mjs https+private-reject; ~25 fonti con fetchImpl nudo → transport protetti; mirror fissati sull’host; validazione dei redirect per habr/hh/geekjob/getmatch; delay(ms, signal) condiviso.
  • FULL-R4 — corruzione della prosa in stripDangerousMarkdown (#513/#518): la rimozione degli scheme avviene solo nei contesti di link/attributo; le entità vengono decodificate in una copia usata solo per il rilevamento («JavaScript: React, Node» e «R&D» sopravvivono).
  • FULL-M2 — irrobustimento dei transport (#520): safeGet onora timeoutMs insieme al signal del chiamante (bridge controller); guardResolvedHost fallisce CLOSED su errore DNS. #525 aggiunge la rimozione degli header di credenziali sui redirect cross-origin, il distacco dei listener dei transport su ogni percorso di conclusione e la correzione di un crash con signal pre-abortito.
  • FULL-M4 — logo/batch (#523): il logo fissa i magic bytes su OGNI percorso (un image/png bugiardo non può trasportare SVG), limita il content-type a image/* al momento dello store, cache privata + nosniff; batch: --parallel limitato a 1–8, --min-score validato, BATCH_BUSY single-flight, llmRateLimit sulle mutazioni di config/batch.

Aggiunto

  • CAR-147 — tetto di valutazione consapevole della locale (#524): evalTimeoutMs(lang) — ta/hi ricevono 480 s invece di 300 s (le scritture indiche tokenizzano più token per sillaba; il vecchio limite produceva 502 + report vuoto); il client remote-QA attende 540 s.
  • CAR-133 — landing v2 di cvstart.org (#532): hero a parallasse vincolato a reduced-motion, una demo SIMULATA chiaramente etichettata del flusso scan→evaluate→tracker, sezioni a reveal allo scroll con conteggi verificati sul vivo, slot segnaposto per gli screenshot di CAR-140.
  • CAR-135 — guida riscritta per la UI v2, fan-out ×18 completo (#533, #540, #541, #542): tutti i 19 file di guida descrivono la shell v2 (nav richiudibile, palette Cmd/Ctrl+K, skeleton, empty state di esempio+azione, chrome della scan v2, pipeline raggruppata+undo, reports v2, kanban); le etichette della UI citano le loro chiavi i18n; la frase delle 121 fonti vive dal registro.
  • Specifiche (SDD/OpenSpec) (#535): backfill della wave-two dell’oct27 + tre specifiche in avanti che documentano l’onda v1.261.0 (fan-out della guida, hand-off delle scritture, invarianti del cambio lingua).

Corretto

  • Il cambio lingua non svuota più #/scan (#534) — segnalato dal proprietario: lo stato di scansione locale alla vista (risultati, chip dei facet) ora è a livello di modulo; harness Playwright comportamentale con un refetch ritardato di 4 s (rosso sulla vecchia forma).
  • CAR-148/149 — report ru «Block G mancante» (#530): il prompt insegnava tre mappe A–G incoerenti; skeleton + elenco + esempio ora concordano con oferta.md (G = Posting Legitimacy); gate di deriva comportamentale.
  • CAR-150 — l’undo della pipeline conserva i metadati comp (#537): DELETE risponde con comp, POST accetta un comp opzionale con gate, la vista trasporta {token, comp} attraverso tutti i rami di fallback.
  • FULL-M3 — le fonti morte riferiscono bacheche oneste (#522): getro/mycareersfuture/meituan/mokahr/glints lanciano un’eccezione su una pagina-1 malformata (un’API morta non si legge più come «sana, 0 offerte»); pinnedOverride fissa gli override company.api di 18 adattatori.
  • FULL-M5 — un’unica cascata di provider (#521): routes/llm.mjs passa per runActiveProvider (+cachePrefix, signal); intercettazione del subprocess Gemini; contratti di risposta identici al byte.
  • FULL-M1 — scritture dei file condivisi sotto lock (#526, #539): runTrackedScript + roster TRACKER_MUTATING; gli spawn di outcome/followup tengono il lock; tracker.mjs scrive via atomicWrite; i salvataggi PUT sono locked+atomic.
  • FULL-M6 — consolidamento server + client (#531, #536, #525): dotenv con prototipo nullo + rifiuto di __proto__; isPrivateOrLoopback copre NAT64/6to4/benchmark/reserved; cache mtime di env-config; GC reale degli slot di file-lock; safeGet timeout+signal; guardia DNS fail-closed; SSE ×4 → API.postStream; librerie focus/label/status; clipboard attesa; tinta Hired nella dashboard.
  • R3 — deriva dei token CSS (#527): --accent risolto (i focus ring della mappa erano silenziosamente morti); 11 durate fuori dai token ripiegate; gate di deriva.
  • R4 — ritardatari del caricamento (#538): assessments/mode-page/pipeline preview rendono gli skeleton di CAR-112.
  • Batch CodeQL + CI (#517, fix #539): import inutilizzati, il gate ACTING_GET importa la regex vera, slice del lifecycle ri-ancorata.

Note

  • Non fatto deliberatamente: il pinning DNS al connect (richiede undici — fuori dalle dipendenze, residuo documentato); gli screenshot di CAR-140 (richiedono la UI v2 distribuita); CAR-137/138/141 (prossima passata di docs); la classe CodeQL js/missing-rate-limiting è un falso positivo documentato (il limiter custom non viene accreditato).
  • Fan-out della guida ×18: la wave-1 di es/de ha saltato la nota d’introduzione e il delta della card Active Companies (de ha fatto atterrare la sua introduzione; es riceve un follow-up di una riga).

[1.260.0] — 2026-10-26

Il treno di irrobustimento delle revisioni — otto merge (#491–#498) dai giri di revisione opus-5-5 e AI sopra la flotta della v1.259.0: normalizzazione dei confronti salariali, perimetro delle date dei report, robustezza della geocodifica, cache-busting del bundle r2+r3, la correzione dell’overflow della deep research — più due UI v2 (pipeline, report). Ogni fix è atterrato tramite un fix-forward rosso→verde.

Corretto

  • Normalizzazione del confronto salariale (CAR-143 rev-2): i marcatori di periodo vengono riconosciuti solo vicino alla cifra a cui appartengono — «6 month contract, $120k» non viene più annualizzato ×12, e le forme di periodo RU/ES attaccate al numero («за месяц» accanto alla cifra) prevalgono sulle parole incidentali; la famiglia di simboli $/¥ viene riconosciuta ma resta non mappata a meno che un codice ISO esplicito non compaia sulla stessa riga (i dollari AUD/CA/SG non vengono più conteggiati come USD, e una forma ¥ RMB riceve un avvertimento esplicito invece di una conversione JPY sbagliata di ~20×); i numeri isolati 19xx/20xx sono sempre anni; le cifre di un intervallo ereditano il periodo dell’altro estremo; il minimum e il target_range del profilo non vengono mai incollati in un unico intervallo.
  • Perimetro di fixReportDate (CAR-144 rev-2): la correzione della data fissata lato server si applica solo al preambolo prima della prima intestazione ## (un report con titolo H2 riceve un no-op conservativo — una data non aggiornata è accettabile, una fabbricata no); nel preambolo: un candidato unico viene corretto, altrimenti un unico **Date:** in grassetto, altrimenti nulla (due candidati in grassetto o due in chiaro non riscrivono nessuno). Il gate FIX-5 delle etichette PDF ora legge il dizionario assemblato reale — una locale mancante solleva un’eccezione invece di passare silenziosamente su un fallback inglese.
  • Chip di località di Habr + robustezza della geocodifica (CAR-142 rev-2): un meta chip di Habr diventa una città solo con un’evidenza strutturale (un link di filtro per città o un’icona di località) — gli avvisi di relocation («Возможна релокация») e i tipi di impiego non si mascherano mai da località; la cache della geocodifica ora sopravvive a un riavvio (flush su beforeExit/exit/SIGTERM+SIGINT con re-raise, il flag dirty azzerato solo dopo che la scrittura è atterrata), l’arresto è delimitato (latch del loop d’uscita, contatore di generazione, LRU per recency), e un budget di geocodifica esaurito risponde 503 + Retry-After invece di un generico 502.
  • Cache-busting del bundle (CAR-145 r2+r3): la shell cita /js/bundle.js?v=<content-hash> — immutabile al combaciamento, no-store al mismatch — eliminando la finestra di deploy di 5 minuti in cui una shell fresca poteva abbinarsi a un bundle vecchio in cache. L’hash e lo stream condividono un unico file descriptor (nessuna lettura parziale); una lettura corta risponde null invece di un hash di ripiego da stat che potrebbe avvelenare un intero deploy; make-bundle scrive l’identity e le compagne .br/.gz tramite un temporaneo col prefisso punto + rename, così una build uccisa non può né servire byte scritti a metà né lasciare in giro il suo file temporaneo.
  • Overflow della deep research (CAR-146): un brief di ricerca salvato il cui solo nome file supera il viewport di un telefono non può più spingere #/deep oltre i 390px — la card si limita alla sua riga, il titolo va a capo, la data resta su una sola riga; il sweep dei viewport stretti ora percorre #/deep con un fixture seminato eccessivamente lungo (l’unico finding dei due run remote-QA, chiuso).
  • Irrobustimento della pipeline v2 (revisione CAR-116): le eliminazioni chiedono conferma e si possono annullare (con un messaggio di undo onesto), nessuna azienda inventata dall’host nelle card, id di riga FNV-1a, conteggi bulk veri, e una guardia di rientranza sulle operazioni bulk.

Aggiunto

  • Pipeline v2 (CAR-116): card arricchite, una vista raggruppata e scarto in blocco con undo; 17 nuove chiavi pipe.* spedite tradotte in tutti i 19 dizionari.
  • Reports v2 (CAR-118): ricerca dal vivo con filtri per fascia di punteggio/legittimità/azienda/data, intestazioni ordinabili (aria-sort), una vista a card persistente con pulsanti d’azione per fascia, un istogramma dei punteggi che filtra al clic, e il rendering unificato «Azienda — Ruolo» / «x.x/5» (window.ReportOps); 31 chiavi rep2.* spedite tradotte in tutti i 19 dizionari.

Note

  • Ogni fix è passato per un giro di revisione con evidenza rosso→verde; i due finding HIGH delle revisioni AI sul primo bundle r2 (hash da lettura corta, atomicità delle compagne) sono chiusi dal r3, e i giri CAR-143/CAR-144/CAR-142 hanno ciascuno riverificato i finding aperti del loro predecessore.
  • Non fatto deliberatamente: la vista a cluster della mappa resta CAR-125 (in coda); il ripristino lato server dei metadati della pipeline è un ticket separato; nessuna correzione retroattiva per i contenuti salvati negli stati pre-rev-2 della v1.259.0.
  • Test 5988 (+165); suite browser 152 pass / 0 falliti / 1 skip opt-in. Nessuna fonte scanner toccata (registro 121 = 116 EN + 5 RU · 116 adattatori); le 48 nuove chiavi i18n sono atterrate con il loro fan-out ×19 dentro le stesse PR delle feature.

[1.259.0] — 2026-10-25

Il secondo treno della flotta di agenti, sei fix: le date dei report sono fissate lato server, il geocoder della mappa mette in cache e legge le città RU, la guida ×18 cita le etichette dei pulsanti localizzate, le frasi della UI smettono di mescolare lingue, i confronti salariali sono calcolati lato server — e il bundle JS viene distribuito precompresso (caricamento a freddo 3.1 MB → 598 KB).

Corretto

  • Date dei report inventate (CAR-101): il prompt di valutazione ora fissa la data odierna lato server («il campo Date: DEVE essere esattamente — copialo alla lettera; non inventare mai»), e fixReportDate riscrive una data deviata a oggi in ogni punto di accettazione (ramo Anthropic, subprocess Gemini, coda OpenAI-compatibile, /api/deep, auto-pipeline) con un warning + un record nell’activity log — una correzione, mai un rifiuto. 349/789 report in produzione portavano date inventate; quelle nuove non possono più.
  • Geocodifica della mappa (CAR-105): le stringhe di città in cirillico delle righe hh.ru/Habr ora arrivano al geocoder; una cache persistente e limitata (data/geocode-cache.json, withFileLock) fa sì che una città già risolta non interroghi mai due volte il provider; le chiamate di geocodifica hanno un budget per richiesta, così la mappa si riempie progressivamente invece di bloccarsi per 13.9 s.
  • UI in lingua mista (CAR-108): 23 perdite con chiave corrette su 17 dei 19 dizionari (85 valori) — «все matching», «только remote», «Открыть Scan», il funnel «Evaluated → Applied…» e altre voci sono diventate frasi localizzate complete che riusano il vocabolario di prodotto di ciascuna locale. i18n-no-latin-leaks esteso con la tabella dei frammenti + la sonda del funnel (rosso→verde).
  • Capovolgimento del verdetto sulle valute (CAR-109): il confronto salariale è calcolato lato server in comp-compare.mjs e incorporato in forma canonica (Candidate minimum: … per YEAR (raw: …) vs JD offer: …); le forme mensili ×12, k/к/тыс/萬 e con virgola decimale si normalizzano prima del confronto; una conversione incerta non può mai da sola capovolgere il verdetto (il caso zh-TW «€80–100k ниже минимума» è morto). Il modello non moltiplica mai.
  • Etichette dei pulsanti nella guida ×18 (CAR-107): i bundle di guida localizzati citavano etichette inglesi («⚡ Run live», «Save», «Scan now») che la UI non mostra più — 263 sostituzioni su 18 locale, mappate dai sorgenti delle viste; il docs-assistant eredita la correzione.

Aggiunto

  • Bundle precompresso + caricamento a freddo cacheabile (CAR-104): make-bundle.mjs emette bundle.js.br (brotli q11) + .gz al momento della release; un middleware limitato al bundle negozia br > gz con Vary: Accept-Encoding, public, max-age=300, must-revalidate + ETag/304; con guardia di freschezza (le varianti compagne non vengono mai servite più vecchie del bundle identity), le richieste dirette degli artefatti rispondono 404, CSP byte-identico. Caricamento a freddo: 3.1 MB → ~0.6 MB in transito (−80%); le visite ripetute entro 5 min trasferiscono ≈0 byte.

Note

  • Tutti i fix arrivano dalla flotta di agenti con evidenza rosso→verde (13 + 28 + 1 + 30 + 7 nuovi casi nelle loro suite) e sono stati rifiniti in giri di revisione (CodeQL #579/#580/#584 corretti nel codice — gli URL degli stub parsati via new URL().host, una stringa morta del prompt eliminata).
  • I numeri del backfill dei punteggi della v1.258.0 sono ora annotati in CAR-129 (updated: 22, reportScoreless: 159).
  • Non fatto deliberatamente: nessuna correzione retroattiva delle date per i 349 report storici (un backfill sarebbe un’operazione da approvazione del proprietario), nessuna vista a cluster della mappa (CAR-125 resta in coda dietro questa correzione della geocodifica).
  • Test 5823 (+74). Nessuna fonte scanner toccata (registro 121 = 116 EN + 5 RU · 116 adattatori); nessuna chiave i18n (CAR-108 modifica solo i valori delle chiavi esistenti).

[1.258.0] — 2026-10-25

Sei fix dalla flotta di agenti, un solo treno: il contatore aziende di #/scan smette di mescolare universi, la deep research esige fonti, gli errori dei moduli illuminano il campo, gli stati di caricamento ricevono skeleton e un h1 immediato, e le valutazioni mettono in cache il prefisso del prompt da 37k token.

Corretto

  • Contatore «Aziende attive» di #/scan (CAR-100): il numeratore contava le aziende distinte su TUTTE le righe di risultato (1554 in produzione — il solo hh.ru ne contribuisce a centinaia) mentre il denominatore contava le aziende tracciate con supporto API (~90) — due universi in una frazione. Abbinamento (a): il numeratore ora conta le aziende tra le righe che la scansione tracciata con supporto API ha recuperato lei stessa (corrispondenza via _entry ?? company; le righe datore di lavoro di hh.ru/telegram escono); il fallback pre-scansione è entrato nello stesso universo (poteva leggere «104/90»).
  • Fabbricazione nella deep research (CAR-110): il prompt deep ora porta un contratto rigoroso — ogni affermazione fattuale termina con [source: domain.com] (se non si può nominare la fonte → non si afferma; inventare un marcatore è peggio che scrivere “unknown”), i fatti sconosciuti si scrivono unknown, e il report DEVE terminare con una sezione ## Data freshness. Ancore di freschezza: la data UTC di oggi + un’opzionale url dell’azienda su POST /api/deep (limitato, mai recuperato lato server).
  • Gli errori dei moduli evidenziano il campo (CAR-130): un POST fallito marca il primo campo del modulo con aria-invalid + .is-error e lo mette a fuoco (WCAG 3.3.1); si ripristina alla modifica. L’hint di errore di rete è consapevole del deployment — il loopback mantiene l’hint del comando dev, un’origine distribuita riceve «server is not responding» invece del consiglio bash web-ui/bin/start.md (il banner di connessione aveva lo stesso hardcode).
  • Stati di caricamento (CAR-112): #/map e #/tracker mostrano il loro h1 all’istante (il bersaglio del focus del router esisteva solo dopo l’arrivo dei dati) e un helper skeleton condiviso (Skeleton.rows, righe shimmer aria-hidden dentro una regione role="status" che riusa common.loading) sostituisce il nudo testo «Loading…» su tracker, risultati della scansione e shell della mappa; prefers-reduced-motion ferma il pulso.
  • Caching del prompt di evaluate (CAR-111): buildEvaluationPromptParts divide il prompt da ~37k token in un prefisso stabile al byte (CV + profilo + file mode + istruzioni) e la coda JD; il percorso Anthropic invia [prefisso + cache_control: ephemeral] + [JD] — il prefisso viene fatturato alla tariffa di lettura della cache (≈10× più economico) a ogni chiamata dopo la prima. Un prefisso mancante o non combaciante ricade in modo aperto alla vecchia richiesta identica al byte; la cascata dei provider compatibile con OpenAI resta intoccata (lì il caching è lato server).

Note

  • Tutti e sei i fix arrivano dalla flotta di agenti con evidenza rosso→verde (5 + 7 + 7 + 7 + 8 nuovi casi) e giri di revisione; i primi alert CodeQL di CAR-111 (#579/#580) sono stati corretti nel codice — lo stub del test parsa l’host dell’URL invece di un matching per sottostringa, e una stringa morta del prompt completo è stata eliminata.
  • Il backfill dei punteggi è girato in produzione (endpoint v1.256.0, approvato dal proprietario): updated: 22, missingReport: 0, reportScoreless: 159 — 159 righe senza punteggio puntano a report le cui intestazioni precedono il blocco macchina o portano formati di punteggio non interpretabili; recuperabili solo con una rivalutazione o una passata di parser più ampia (annotato in CAR-129).
  • Non fatto deliberatamente: nessuna modifica nulls-last per la colonna commute (quirk preesistente Infinity-on-desc), nessun re-pricing retroattivo delle vecchie righe di usage, nessuna evidenziazione in stile .is-error per i moduli di filtro della scansione (CAR-130 delimitato all’helper condiviso di submit della mode-page + l’hint di api.js).
  • Test 5749 (+36). Nessuna fonte scanner toccata (registro 121 = 116 EN + 5 RU · 116 adattatori); nessuna chiave i18n (l’hint di CAR-130 riusa conn.down; la regione skeleton riusa common.loading).

[1.257.0] — 2026-10-25

Due fix della flotta di agenti: l’assistente della guida in-app capisce devanagari e tamil, e la pagina usage mostra quanto costa davvero Hermes.

Corretto

  • Recupero dell’assistente della guida per hi/ta (CAR-103): la classe di caratteri di parola del tokenizer a keyword del docs-assistant era [\p{L}\p{N}\u30fc]+ — senza segni combinanti. Ogni matra devanagari (ा ै ्…) e ogni segno vocalico tamil (ே ை ்…) spezzava una parola in frammenti; la regola sulla lunghezza scartava i frammenti corti (una query in hindi combaciava con 0 sezioni) e le parole più lunghe venivano decapitate in spazzatura che collimava con sezioni non correlate. La classe ora mantiene \p{M}; il percorso dei bigram CJK resta intatto. hi «मैं स्कैन कैसे चलाऊं?» e ta «ஸ்கேன் எப்படி இயக்குவது?» recuperano le sezioni giuste dai bundle distribuiti.
  • Costo dell’uso per Hermes (CAR-106): normalizeUsage() collassava l’usage del provider a {in, out} e scartava silenziosamente il cost riportato dal gateway — #/usage mostrava $0.0000 su 9.5 M di token Hermes (la sua riga nella tabella dei prezzi è 0/0). La forma del record di usage guadagna un cost? opzionale e retrocompatibile; l’aggregatore preferisce, per ogni record, il costo riportato dal provider e ricade alla stima della tabella dei prezzi solo in sua assenza; i valori spazzatura/negativi vengono scartati, mai fabbricati.

Note

  • Entrambi i fix arrivano dalla flotta di agenti con evidenza test rosso→verde (3 + 5 nuovi casi; 14/14 e 10/10 verdi; i vicini 78/78 e 61/61). Le prime PR (#470/#471) portavano una base di worktree obsoleta che confliggeva con la v1.256.0 unita in squash — sostituite da cherry-pick puliti (#472/#473).
  • Non fatto deliberatamente: nessun re-pricing retroattivo delle righe storiche di data/llm-usage.jsonl (non portano un campo cost; ne beneficiano solo i nuovi record).
  • Test 5713 (+8: docs-assistant ×3, usage ×5). Nessuna fonte scanner toccata (registro 121 = 116 EN + 5 RU · 116 adattatori); nessuna chiave i18n.

[1.256.0] — 2026-10-25

Qualità dei dati del tracker: il ruolo non viene mai registrato come azienda, un job board non viene mai registrato come datore di lavoro, le righe senza punteggio smettono di emergere per prime — e un endpoint one-shot recupera i punteggi mancanti direttamente dai report stessi.

Aggiunto

  • Backfill dei punteggi (CAR-129): POST /api/tracker/backfill-scores riempie la cella Score delle righe il cui report collegato porta un punteggio interpretabile (181 righe valutate avevano un report ma nessun punteggio). Le righe con punteggio, le sentinelle esplicite (N/A), le righe senza report e i report senza punteggio non vengono mai toccati; viene riscritta solo la cella Score, sotto file lock; la forma del punteggio è validata nel punto di scrittura e normalizzata alla convenzione X.X/5 del tracker; l’esecuzione è idempotente e restituisce {ok, updated, missingReport, reportScoreless}.

Corretto

  • Il ruolo non è mai l’azienda (CAR-128): guessCompanyRole trattava il lato SINISTRO di una riga di intestazione col trattino come l’azienda, ma i board scrivono entrambi gli ordini — «Senior Frontend Engineer - Grafana Labs» registrava il ruolo COME azienda (13 righe: Grafana, CircleCI…). Un’euristica sulle keyword di ruolo con confine di parola ora sceglie il lato del ruolo, e un tipo di impiego non diventa mai il datore di lavoro («Senior Engineer - Remote (EU)» non registra nulla invece di registrare «Remote (EU)»).
  • Un job board non è mai il datore di lavoro (CAR-127): il fallback sullo slug di dominio registrava le righe hh.ru come «hh» (120 righe). Gli slug hh/habr entrano nell’elenco dei non-datori di lavoro; l’inferenza del datore di lavoro a metà frase («в компании X», «X ищет») ora gira anche per gli host dei job board (hh.ru/kz/uz/by, habr.com) — dove il testo della pagina nomina il vero datore di lavoro. Causa radice scoperta lungo la strada: i \b/\w ASCII di quei pattern di inferenza non hanno mai combaciato con il cirillico — silenziosamente morti dalla v1.248.4; lookbehind Unicode e classi \p{L} li sostituiscono.
  • Le righe senza punteggio si ordinano per ultime (CAR-129): l’ordinamento per punteggio del tracker usava un valore sentinella -1, così con l’ordinamento ascendente predefinito ogni riga senza punteggio emergeva prima di ogni riga con punteggio. I null ora si ordinano per ultimi in entrambe le direzioni (il FILTRO sul punteggio mantiene il suo -1 — «senza punteggio fallisce un filtro ≥4» è la semantica corretta in quel caso).

Note

  • Le righe storiche NON vengono migrate da questa release: le correzioni del parser si applicano alle nuove valutazioni; i punteggi sono recuperabili tramite l’endpoint di backfill, mentre le 120 celle del datore di lavoro «hh» richiedono una rivalutazione, non una riscrittura.
  • Un giro di revisione opus-5-5 è incorporato: il pattern non ancorato «X ищет» è stato scartato prima della spedizione (qualsiasi sequenza con iniziale maiuscola prima del verbo sarebbe stata registrata come datore di lavoro — l’invariante no-fabrication), aggiunti gli ancoraggi «В…» a inizio frase, e il writer del backfill ricontrolla la cella bersaglio (esistono righe # duplicate dopo modifiche manuali), mantiene il numero di colonne di una riga corta malformata a mano e si ferma alla prima riga non-tabella. Il punto dentro un nome puntato («Сбер. IT») è indistinguibile da un punto di frase per l’ancoraggio «в компании» — viene registrato il prefisso conservativo («Сбер»); il pattern ancorato al verbo cattura la forma completa.
  • Non fatto deliberatamente: nessuna estrazione del comparatore da tracker.js in una lib testabile con unit test (il gate source-static resta; annotato in CAR-129 come follow-up), nessuna modifica nulls-last per la colonna commute (quirk preesistente Infinity-on-desc), nessuna migrazione dati per le righe «hh».
  • Test 5705 (+10: 5 identity in auto-pipeline-jd-gate, 2 CAR-128, il gate dell’ordinamento CAR-129, 4 di backfill incluso il pin del percorso ostile — meno i casi v1.248.x sostituiti). Nessuna fonte scanner toccata (registro 121 = 116 EN + 5 RU · 116 adattatori); nessuna chiave i18n.

[1.255.2] — 2026-10-24

Tre fix visibili all’utente dalla regressione live e da una segnalazione di crash in produzione: il crash del render di #/scan, il controllo linguistico cieco per il vietnamita e la perdita ricorrente del blocco summary in zh-TW.

Corretto

  • Crash di #/scan (CAR-99): dalla v1.253.0 la rigenerazione dei count-gate ha scritto il letterale FALLBACK_SOURCES con una virgola doppia finale su ogni voce — 120 buchi di elisione nell’array. new Set(FALLBACK_SOURCES.map((s) => s.value)) nella vista scan conteneva allora undefined, e l’id.length del classificatore di aziende lanciava TypeError: Cannot read properties of undefined (reading 'length') a ogni render di pagina (colto da logbuf in produzione). I buchi sono rimossi e un nuovo gate (4 specifiche, verificato in rosso) esegue il file e fallisce su qualunque buco, voce inutilizzabile o undefined nel Set degli id adattatore — il gate di deriva solo-testuale non poteva vedere questa classe.
  • Controllo linguistico cieco per il vi (CAR-97): il vietnamita è in alfabeto latino e non aveva voce nella tabella delle stop-word della QA live, quindi le «vi stop words» contavano le occorrenze inglesi e una risposta vietnamita risultava report not in vi (regressione live: vi 2, en 2). Il vietnamita ora ha la sua tabella di dieci parole funzionali — un report puro in vi passa, uno in inglese fallisce ancora.
  • zh-TW ha perso il blocco SCORE_SUMMARY (CAR-98): il promemoria linguistico di chiusura diceva solo che il formato macchina non va tradotto, mai che il blocco summary deve esistere — un report zh-TW corto (5.983 caratteri) portava i blocchi A–G ma ometteva il blocco del tutto (una ricorrenza della classe v1.239.2). La direttiva di apertura e il promemoria di chiusura ora dichiarano che il blocco è obbligatorio e che il report senza è invalido.

Note

  • Questa release non cambia deliberatamente alcuna fonte scanner, né il conteggio del registro (121 = 116 EN + 5 RU · 116 adattatori), né il cablaggio dei provider — sono solo fix, quindi i count-gate restano intatti.
  • Test 5695 (+9: car99-fallback-holes ×4, car97-vi-lang-check ×4, l’invariante del prompt CAR-98 ×1). Browser 143/143. Il ri-controllo live vi/zh-TW viaggia con la regressione post-deploy.

[1.255.1] — 2026-10-24

Due giri di correzioni dalle revisioni: la revisione Opus della localizzazione vietnamita (9 reperti) e la revisione di seconda passata dei fix CAR-91/92 (5 imperativi) — entrambi chiusi con test rosso→verde.

Corretto

  • Giro di revisione della locale vi (follow-up di CAR-88): il glifo Hangul (신) che era filtrato in project.subtitle / project.roleHint è corretto (độ khớp tín hiệu), con un gate che fallisce su qualunque glifo CJK/Kana in un valore vi che il dizionario EN non porta; i sei URL markdown con spazi in docs/help/vi.md (what-is career-ops, apply for a job, set up playwright e altri tre) sono riportati col trattino agli slug reali delle guide, con un gate che vieta gli spazi negli URL.
  • Confini delle intestazioni di valutazione (CAR-92 r2 H1): &, ., /, ' sono ora caratteri di parola nel confine sinistro della lettera-blocco — ## Q&A, ## Plan B, ## Ph.D. requirement, ## E-commerce non si registrano più come blocchi A/B/D/E; il terminatore nudo a fine riga è accettato solo dopo un token parola-blocco (Block/блок/블록/…); l’ASCII - è uscito dalle classi dei terminatori scritti per esteso, così le intestazioni E-commerce/ई-मेल sopravvivono.
  • Report numerati in ucraino/russo (CAR-92 r2 H2): il rilevatore della sequenza А Б В Г Д Є Ж è ora un helper condiviso; quando trova 3+ lettere della sequenza a un livello di intestazione, quel livello diventa il livello di riferimento del cutter — le sottosezioni ### A. con lettera non troncano più il report al blocco Б.
  • Ciclo di vita delle righe riportate (CAR-92 r2 M1): le righe che una fonte fallita riporta nella scansione successiva vengono timbrate carriedSince, scartate dopo 30 giorni o 5 riporti consecutivi, e accodate dopo le righe fresche invece di ri-accumularsi in silenzio per sempre.
  • Denominatore della gemini-synthesis + legitimacy (CAR-92 r2 M2) e il percorso subprocess del body-score (M3): letti dal file dei reperti, corretti con test rossi.
  • Gate di deriva del bundle a caricamento a freddo aggiornato per il dizionario vi (90 tag script / 87 bundleizzabili) e rimossa la sua associazione di test inutilizzata (CodeQL 572).

Note

  • La formulazione del conteggio adattatori nel banner «Ultima» del README.vi segnalata dalla revisione sta nel banner Precedente e rispecchia già il README EN byte per byte — lasciata intatta per mantenere la parità EN↔vi (documentata nel corpo del commit).
  • Test 5686 (+26: eval-validate-opus-r2, scanner-carryover-r2, asserzioni dei gate vi). Registro invariato a 121 fonti (116 EN + 5 RU) · 116 adattatori.

[1.255.0] — 2026-10-24

Il vietnamita (Tiếng Việt) entra come 19ª lingua dell’interfaccia — un dizionario di 1525 chiavi in piena parità con l’EN, rilevamento di vi/vi-VN, il pacchetto guida completo, i mirror README e CHANGELOG, l’integrazione nella landing di cvstart.org e il 🇻🇳 nel selettore lingua.

Aggiunto

  • Vietnamita (vi) — 1525/1525 chiavi in piena parità con en; detect() accetta vi e vi-VN; il vietnamita è LTR (mai aggiunto a RTL_LANGS). ‘Pipeline’ resta ‘Pipeline’ — prestito tecnico standard, in whitelist.
  • docs/help/vi.md completo (33 H2 / 125 H3), più i mirror README.vi.md e CHANGELOG.vi.md e le stringhe-scaffold in vietnamita in prompts.mjs (LOCALE_NAMES + SCAFFOLD_STRINGS) — l’output LLM in vietnamita funziona fin da subito.
  • Landing di cvstart.org in vietnamita — site/src/i18n/vi.json, la voce locale della sitemap e uno screenshot dashboard-vi.png; il selettore lingua guadagna il 🇻🇳 (19 posizioni).
  • Cancelli di enumerazione 18 → 19 — LANGS, sonde detect, audit i18n, parità del changelog, blocco traduzioni README, spazzata locale — più il tests/i18n-vi-locale.test.mjs red-first (139 righe).

Note

  • La landing di cvstart.org guadagna il vi — una deviazione deliberata dal precedente ta (quel rilascio teneva la landing a 17 di proposito); documentato nella specifica del rilascio.
  • vi è in scrittura latina, quindi il cancello no-latin-leaks non si applica (custodisce le lingue non latine); il lessico tecnico latino qui è la norma.
  • Pavimento dei test: 5634 → 5642 (1 saltata = il test browser opt-in di cattura del layout, invariato).

[1.254.0] — 2026-10-24

Una versione di indurimento dal giro di revisione col modello massimo: lo snapshot dello scanner non perde più righe, undici violazioni d’invariante del layer LLM sono corrette, ventitré must-fix SPA atterrano, e l’ATS Paylocity si unisce allo scanner — il registro ora fornisce 121 fonti (115 EN + 5 RU) con 116 adattatori.

Aggiunto

  • ATS Paylocity (parent #5687): board per tenant recruiting.paylocity.com, board morto 302 → JobNotFound mappato a 404 così la quarantena va in pensione la voce, cap max_jobs con flag di troncamento. Registro: 121 fonti = 116 EN + 5 RU · 116 adattatori; i gate di conteggio rigenerati.

Corretto

  • Sicurezza dello snapshot dello scanner (R-12): una scansione che non tenta nulla CONSERVA ora lo snapshot (nothing scanned); un replace completo riporta le vecchie righe delle fonti fallite — timbrate per voce — ripassate nei filtri ATTUALI, atterrando solo in filtered.
  • Undici violazioni d’invariante del layer LLM: la direttiva di lingua apre E chiude i prompt deep/mode; il subprocess Gemini inoltra --lang, exit non-zero → 502, non fa più filtrare il stderr al client, rispetta i 300 s e registra l’usage; il fallback manual porta l’URL dell’annuncio; truncation e warning del bundle emergono in /api/mode; il spend tier non è più sovrascrivibile dal client; la disconnessione del client abortisce la chiamata al provider in volo; il cutter delle intestazioni ripetute non distrugge più report validi; gli estrattori score/legitimacy concordano col validatore; la sequenza ucraina e il wa arabo sono stretti.
  • Un giro di revisione Opus 5-5 SUI fix stessi (8 imperativi): la registrazione multi-lettera del cutter, terminatori di intestazione più larghi, il cablaggio di abort del subprocess Gemini, l’attribuzione timbrata del riporto, le righe riportate ripassano i filtri attuali, il livello di riferimento per lettere distinte.
  • Ventitré must-fix SPA nelle viste di sourcing (l’append del pager a pagina singola, la tastiera delle righe pipeline, il ripristino dei filtri saved-search, i reset del select source, il ritorno al default in config, le fughe di listener, la chiusura SSE al terminale, il teardown del runner di scansione, un fetch nudo, i caricamenti falliti che sembravano vuoti, una collisione globale, la conservazione del focus) e nelle viste di assistenza (il deep-link morto dell’help, le fughe di listener dell’help, il riarmo del blank-overwrite del two-pager, il single-flight delle esecuzioni a pagamento batch/deep/mode, le fini silenziose di stream, i percorsi d’errore a spinner eterno, le righe fantasma dei filtri falliti, i duplicati docs-fab + la lingua).

Note

  • L’intero giro è stato rivisto da Opus 5-5 al massimo rigore — i port pre-merge (21 reperti, 13 corretti) e i fix stessi post-hoc (8 imperativi, tutti qui con test rosso→verde).
  • Pavimento dei test: 5262 → 5634 (372 nuove specifiche su fonti, scanner, layer LLM e SPA).

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