Changelog
GitHubTodas as mudanças relevantes, versão por versão. O mesmo arquivo é publicado no repositório e traduzido nos 19 idiomas.
[1.267.1] — 2026-11-04
Corrigido
- Reparo do trem de releases (os gates de CI do v1.267.0) — a cadeia de contagem de testes no PROJECT-CONTEXT não quebra mais na cabeça do v1.267.0 (o formato de seta que o eval grader casa), os prompts de QA são reorganizados (um prompt vivo por release, v1.266.0 arquivado) e a cobertura por arquivo sobe acima do ratchet 98/90: o renderizador de salário do applicantpro perde um fallthrough inalcançável (salaryRangeOf devolve, de forma demonstrável, undefined, {min}, {max} ou {min,max}) com os ramos unilaterais ≥/≤ agora fixados através do fluxo de fetch, e a suíte board-response-cache fixa o bypass de no-store, o 304 fornecido pelo chamador contra um board não salvo e a expulsão em MAX_ENTRIES.
- Testes: a contagem ao vivo é 7395 (as suítes da onda v1.266.0/1.267.0 carregam mais specs do que as notas anteriores acompanharam — a cadeia é re-ancorada no piso medido: 7392 após a onda, + 3 testes de gate neste patch); cobertura 98.51 linha / 90.35 ramo.
Notas
-
A tag v1.267.0 permanece apontando para o commit vermelho do merge — não é re-apontada (o servidor recusa tags re-apontadas); v1.267.1 é o veículo de deploy.
-
Reparo em patch do trem v1.267.0: gates de CI verdes, a árvore de código não mudou em substância.
[1.267.0] — 2026-11-04
Adicionado
- Quatro novas fontes de varredura — GermanTechJobs, Darwinbox, Keka, ApplicantPro/isolved (registro 125 → 129 = 124 EN + 5 RU · 124 adapters) — a segunda onda de parent-sync contra career-ops @
7d8feb6d(87 commits upstream). GermanTechJobs (#6346): RSS de todo o quadro emgermantechjobs.de/rss(~626 itens numa única requisição); o empregador é o último segmento" @ "do título — um título sem esse segmento é descartado, nunca registrado sob o quadro; seleção apenas viaprovider:explícito. Darwinbox (#6416): JSONalljobssem autenticação atrás de<tenant>.darwinbox.in, o id da empresa vem da URL de careers, caminhada POST paginada (50/página,max_pages20/200) com a parada por página curta lida da própria contagem de linhas da fonte. Keka (#6199): duas requisições — um shell de careers comredirect:'manual'cujo script nomeia o UUID do feed (um tenant desconhecido responde 302 paraTenantNotFound.htmle é lido como um 404 nomeado), depois todo o inventário aberto num único array de embed-jobs. ApplicantPro / isolved (#6252): odomainIdnumérico extraído do bootstrap, depois{success, data:{jobs, jobCount}};jobCount > rowsavisa que a lista está incompleta; o opt-inapplicantpro: { fetchDetails: true }enriquece via JSON-LD com pausa de 250 ms. - Reúso de resposta de quadro via ETag (#6105) — dentro de uma mesma varredura, a resposta de um quadro obtida nos últimos 15 minutos é reusada como está e as mais antigas revalidam com
If-None-Match(o 304 mantém o corpo); a chave do cache cobre método + URL + headers de credencial + corpo, leituras concorrentes colapsam na promise em andamento, eCAREER_OPS_HTTP_CACHE=0/_TTL_MSfazem override. Em memória, por execução de varredura (a web-ui não tem contrato de cache em disco) — desvio registrado.
Corrigido
- Datas em quatro quadros (#6274) — remoteok, remotive, workingnomads e IBM agora emitem data de publicação, então o filtro «Posted within» funciona nelas; o timestamp naive do remotive é normalizado para UTC (o bug de idade por máquina dele estava ativo), e o
_sourceda IBM agora realmente pededcdate. - Uma chave grafada errado no portals.yml é rejeitada (#6107) — a varredura EN agora lança um erro nomeado (arquivo + chave + sugestão da chave mais próxima, Levenshtein ≤ 2) antes de qualquer fetch, em vez de ignorar silenciosamente
titel_filter:. - getro segue a caminhada além de um pin destacado antigo (#6406) — uma vaga fixada obsoleta continua descartada, mas não encerra mais a paginação; a caminhada termina numa página curta de verdade.
Notas
- Deliberadamente não feito: o seen-filter do scanner RU não é ciente de língua e o caminho de parse do portals dele não roda o gate de chave grafada errado (hand-offs registrados na spec da onda — nenhum quadro RU emite linhas por língua ainda); o remoteok mantém sua string de data com offset em vez de normalizar para UTC (o formato ao vivo dele é determinístico). Tests 7096 → 7243; Playwright 173 pass / 0 fail / 1 opt-in skip; registro 129 = 124 EN + 5 RU · 124 adapters (todos os portões de contagem regenerados do registro vivo).
[1.266.0] — 2026-11-01
Adicionado
- As versões de língua do Personio deixam de se eliminar mutuamente (CAR-223: parent #4789 + #5044 + #5285) — o stack que estava deferido, executado como release próprio. Lado da varredura (#4789):
scan_history.dedup_include_language: true(opt-in estrito — OFF é byte-idêntico) faz as versões de língua de uma mesma vaga sobreviverem ao dedup via a maquinaria de variantes do seen-history (languageFormsFromUrl/recordUrlVariant/isUnseenLanguageVersion); a chave canônica remove os paramslanguage/lang/locale. preferred_languages (#5285): ordena as linhas de versão de uma vaga com a preferida primeiro (estável, ordem do provider em empates) — independente do switch (OFF mantém a versão preferida, ON mantém todas as versões nessa ordem), com um port dovalidatePreferredLanguagesde validate-portals. Fan-out do personio (#5044): a página de careers é buscada sem a força do?language=en(o?language=xxpróprio do tenant é honrado) e emite uma linha por versão de língua, com URLslanguage+?language=<code>; odedupIncludeLanguageadiciona fetches por língua (cap 5, com pausa); os fallbacks /xml e job-link ficam inalterados. recruitee ganha a mesma emissão delanguage+preferred_languages(opts ou entrada). Os helpers compartilhados vivem emserver/lib/language-preferences.mjs.
Notas
- Hand-offs registrados, deliberadamente não feito: o seen-filter do scanner RU não é ciente de língua e nenhum quadro RU emite linhas por língua ainda; o mirror client
url-key.jse a ligação da validação da rota de portals seguem em aberto. Tests 7096 → 7203; registro inalterado 125 = 120 EN + 5 RU · 120 adapters.
[1.265.0] — 2026-11-01
Adicionado
- Duas novas fontes de varredura — Apple e Bulldogjob (registro 123 → 125 = 120 EN + 5 RU · 120 adapters) — onda de parent-sync contra career-ops @
fe857ecf. Apple (jobs.apple.com, #5496 + #6196): o site é um app React Router SSR sem API JSON utilizável, então a fonte lê o blob de hidratação da rota de busca comum (window.__staticRouterHydrationData); a descoberta é definida pela entrada (apple.queriescom ordenação por relevância + eixosapple.teams, sem padrões — uma entrada sem nenhum lança erro), as páginas são limitadas pormax_pages(2 padrão, teto 50) com pausa de 200 ms, cada segmento de URL é codificado contra surrogates e uma vaga marcada PIPE pela Apple carrega no snippet a nota «pode ser um talent pipeline» — nada é filtrado por isso. Bulldogjob (bulldogjob.pl, #6253): o quadro polonês também não tem API JSON — as listagens trazem__NEXT_DATA__(50/página,totalCount); ocareers_urlda entrada é a busca montada no site (os filtros vivem no caminho), cada requisição leva um/page,Nexplícito e a caminhada para em página curta, no total declarado ou emmax_pages(25 padrão, teto 100) com etiqueta de truncamento em quadros parciais. - Rework da paginação da IBM (#6273) — a caminhada fixa de 600 registros vira
max_pages(20 padrão, teto 300, override por entrada) com pausa de 200 ms entre páginas e retry por página viafetchJsonWithRetry; uma primeira página falha lança erro, uma página posterior falha mantém o coletado e nomeia a página, e só uma página completa no teto próprio da entrada avisa «raise max_pages».
Corrigido
- justjoin data as vagas por
lastPublishedAt(#6254) — opublishedAtda API de candidatos avança a cada atualização do empregador, então a maior parte do quadro carregava a data de hoje e omax_posting_age_daysdeixava passar vagas de semanas; agora vence a data de publicação anterior, com fallback quando falta ou não parseia. - jobvite dobra linhas que compartilham um posting URL (#6127) — um feed público devolve uma linha
<job>por cidade para um único detail URL; o parser guardava a primeira cidade e contava o resto como duplicados. Agora os irmãos contribuem só com localidades, unidas com·na ordem do feed, o primeiro título/data permanece e «remote» é reavaliado sobre a localidade unida. - Liveness: um rung para UltiPro (#6090) — a UKG não tem endpoint JSON por vaga e responde 200 nas fechadas, então todas as 57 vagas UltiPro fechadas liam uncertain. A página de detalhe embute o registro:
OpportunityIsClosedtrue/false → expired/active, o aviso «opportunity unavailable» → expired, qualquer outra coisa fica com o navegador. O banner da Built In «Sorry, this job was removed» virou hard-expired (#6336) — a página mantém o JD completo e o controle APPLY; agora o banner vence, e o badge irmão «Job removed» sem «sorry» não casa.
Notas
- Deliberadamente não feito: a metade parent-side do fix do jobvite sobre o compilador de localidades do scan.mjs (web-ui documenta o compilador USPS como no-port) e o campo
notedo pai para a dica PIPE da Apple (o job shape da web-ui não temnote; ela viaja nosnippet). Tests 7096 → 7135 (+39); Playwright 173 pass / 0 fail / 1 opt-in skip; coverage gate ≥ 98/89; registro 125 = 120 EN + 5 RU · 120 adapters (todos os portões de contagem regenerados do registro vivo).
[1.264.3] — 2026-11-01
Corrigido
- Onda de endurecimento do rate-limit (LOW №1–3 da revisão, em
REVIEW-2026-10-31-v1.264.1) — owriteRateLimit()(express-rate-limit@7.5.1, 60 req/min route×IP, 429 JSON + Retry-After) agora cobre todos os 47 endpoints mutantes (eram 2): 9 guardsllmRateLimitmal escopados foram substituídos (/api/config— a reescrita do.env!,PUT /api/batch,/api/batch/merge, outcome, followup/seed, assessments, stats/snapshot, mock-interview/save, networking/save), 3 ficam empilhados antes do bucket de LLM nos caminhos caros (/api/evaluate,/api/deep,/api/auto-pipeline), e 33 rotas bare foram ligadas (editores de CV/profile/modes, todas as escritas do tracker, pipeline POST/restore/DELETE, jds, os 7/api/run/*via uma única edição de loop, posting-guard, Playwright-PDF inline, portals toggle/health/track, discover, reports, export/docx, two-pager, career-plan, memory e as três rotas DELETE)./api/apply-helperpermanece allowlisted bare (computação puramente local, pinado); 16 rotas puramente de LLM mantêm por design o bucket condicional de LLM. Um tripwire de completude (tests/rate-limit-coverage.test.mjs, red-first com 27 bare) quebra o CI caso qualquer rota mutante futura seja registrada sem throttle. TRUST_PROXYopt-in + validações re-armadas (LOW №1–2 da revisão) — oapp.set('trust proxy', N)honra um hop countTRUST_PROXYdo env (nuncatruebooleano — isso chavearia pela extremidade esquerda do XFF, controlada pelo atacante); sem valor por padrão, então o loopback mantém sua degradação documentada por rota com chave de socket. Ovalidate: falsevira umwriteValidateConfig()direcionado: só oxForwardedForHeaderfica de fora (o XFF do Caddy é ignorado por design sem trust proxy), e toda outra validação — incluindotrustProxy— volta a ser ruidosa, de modo que um futuro erro de configuraçãotrust proxy: trueapareça comoERR_ERL_PERMISSIVE_TRUST_PROXYem vez de silêncio. OkeyGeneratorcustomizado foi removido de propósito: o express-rate-limit amarra suas validações de proxy ao gerador de chave default, e o isolamento por rota fica inalterado (umMemoryStorepor chamada de factory).- O feedback da copy do cvstart.org reverte depois de 2 s (CAR-141) — o estado «Скопировано ✓» agora segura os 2 segundos do critério de aceitação (eram 1.5 s), pinado red-first em
tests/site-copy-feedback.test.mjs. Isso fecha o último critério do CAR-141 corrigível por agente; a atualização do vídeo de demo segue deferida pelo dono (decisão de 2026-11-01).
Alterado
- Os bundles de help dizem 19 línguas (×19) — as frases da §19 “Localizing the app” e da §32 “Run it from OpenWorker” não ficam mais duas localidades atrás: todo bundle agora diz 19, com தமிழ் e Tiếng Việt no seu próprio estilo de enumeração (ar usa o «التسع عشرة» por extenso), e o remanescente «cả-17» da própria §32 do
vi.mdtambém é corrigido. Os gates de estrutura (33 H2 / 125+ H3) ficam byte-estáveis. - Higiene de estado — o
AGENTS.mddeclara v1.264.2 / 7082 tests (era v1.86.x / 1566); oPLAN.mdmarca os releases 1–7 como Shipped e o parágrafo do ship-train dele diz docs ×19; o comentário doStatsBar.astroagora descreve o que ofacts.adaptersrealmente guarda (123 = total de sources, nome histórico da chave mantido para os consumidores); o cabeçalho doi18n.jsdiz 19 línguas; o QA prompt da v1.264.2 carrega a cobertura real (98.45/90.05) e a aritmética do Playwright (176 = 174 harness + 1 opt-in skip + 2 suítes de nível de script).
Notas
- Deliberadamente não feito: a onda de parent-sync conforme a port-list registrada fica no BACKLOG — o fork precisa sincronizar além do upstream
a9476866primeiro (7 dos 10 commits da port-list ainda não estão na árvore local do pai; IBM/UltiPro/Bulldogjob/apple com escopo S–M, personio language-dedup deferido para o próprio release). O re-record do vídeo de demo do CAR-141 segue conscientemente deferido pelo dono («видео не надо пока», 2026-11-01). - Tests 7082 → 7096 (+9 tripwire de cobertura + 5 trust-proxy); Playwright 173 pass / 0 fail / 1 opt-in skip (+2 pins de setinha dentro de cases existentes); cobertura 98.46 linhas / 90.10 branches; evals 14/0/1skip; registro inalterado 123 = 118 EN + 5 RU · 118 adapters.
[1.264.2] — 2026-11-01
Corrigido
- Os cabeçalhos de grupo da sidebar aderem ao contrato de truncamento (CAR-219) — os rótulos dos toggles de grupo (
.nav-v2-toggle > span) agora truncam com reticências e carregam um tooltip localizado pelo mesmo mecanismosyncLabelTitles()dos itens de nav do CAR-203; a setinha nunca encolhe, o toggle continua clicável, o RTL se mantém. Pin red-first emtests/nav-v2.test.mjs(+1 → 7082 tests).
Alterado
- A copy do cvstart.org chega em todas as 19 línguas (CAR-220) —
meta.helpDesc,helpTeaser.c1.descefaq.a2estão traduzidos em toda localidade do site (eram somente EN na v1.264.1 por design); o GitHub Pages publicou a copy atualizada ao vivo no cvstart.org. - Higiene do backlog + revisão (CAR-221/222) — os seis itens «port when merged upstream» estão fechados: todos os sete PRs upstream estão mergeados, quatro itens já haviam sido portados, dois são do lado do pai.
docs/reviews/REVIEW-2026-10-31-v1.264.1.mdchega (0 HIGH / 0 MED, três follow-ups LOW registrados no BACKLOG), e a port-list do parent-sync fica registrada (6 PORT / 3 VERIFY / o gap da fonte apple; cauda upstream de 118 commits @ VERSION 1.38.0).
Notas
- A correção do mirror-stamp do changelog (
92a05fcf) vem nesta tag: todo mirror paginado no cvstart.org agora carrega a versão do release gerador, de modo que o gradersite-build-after-fanoutfinalmente exerce sua lógica real em vez de pular. - Deliberadamente não feito: o throttling dos POSTs mutantes restantes (LOW №3 da revisão) e o acoplamento de buckets do trust-proxy — registrados no BACKLOG para a próxima onda de endurecimento. CAR-141 (vídeo de demo) continua sendo do dono.
- Tests 7081 → 7082 (+1 pin do CAR-219); Playwright 176; registro inalterado 123 = 118 EN + 5 RU · 118 adapters.
[1.264.1] — 2026-10-31
Corrigido
- As pills da sidebar truncam com elegância rótulos localizados longos (CAR-203) — o span do rótulo da nav agora é um cidadão flex de verdade (
min-width: 0+overflow: hidden+text-overflow: ellipsis+nowrapemv2-nav.css), esyncLabelTitles()emnav-v2.jsespelha o rótulo localizado no tooltip pela mesma chavedata-i18n(zero novas chaves i18n) — o longo «Профинансированные компании» volta a ser legível no hover em vez de ser cortado na força pelooverflow: hiddenda linha. O alvo de toque de 44 px, a pintura do estado ativo e o espelhamento RTL ficam intocados; pin red-first emtests/nav-v2.test.mjs. - Um teto único de avaliação de 480 s para toda localidade (CAR-218) — o remote-QA da v1.264.0 capturou avaliações
502 · 300 s · 0 chtransitórias emesezh-CN(o re-run pontual passou, mas a parede era real).EVAL_TIMEOUT_MSagora é480_000eevalTimeoutMs(lang)o retorna incondicionalmente —GEMINI_EVAL_TIMEOUT_MSe o auto-pipeline herdam. O orçamento de tokens por localidade do CAR-174 (16384 / 32768) continua sendo o único split por localidade.
Alterado
- O FAQ do cvstart.org carrega contagens exatas de fontes (CAR-217) —
{sources} job-board sources: {sourcesEn} international boards plus {sourcesRu} Russian onessubstituído a partir dofacts.json, gerado do registro ao vivo (123 = 118 EN + 5 RU), de modo que os números nunca podem divergir; as localidades que ainda têm a redação antiga~{adapters}continuam arredondando viaadaptersRounded. Os upgrades de copy em EN acompanham (meta.helpDesc,helpTeaser.c1.desc,faq.a2citam o menu de comandos, o pipeline agrupado com undo e o tracker kanban).
Notas
- Deliberadamente não feito: os upgrades de copy do i18n do site (
meta.helpDesc/helpTeaser.c1.desc/faq.a2) ficam somente em EN neste release — as outras localidades mantêm redação correta, porém mais genérica, até a próxima onda de docs (ofaq.a7delas ganha os placeholders de contagem exata onde traduzido). CAR-141 (vídeo de demo) continua sendo do dono; a branch substituídacar136/m141foi deletada com as ideias registradas na task da Linear (recuperável via tagarchive/car136-m141). - Tests 7041 → 7081 (pin do CAR-203 + reescritas do pin do CAR-218); Playwright 176; registro inalterado 123 = 118 EN + 5 RU · 118 adapters.
[1.264.0] — 2026-10-31
Adicionado
- Edição inline do status do tracker — o badge de status de cada linha do
#/trackeré um<select>compacto com as etapas canônicas (deGET /api/tracker/stages, nunca uma whitelist hard-coded).POST /api/tracker/statusrepassa oset-status.mjscanônico do pai sob o lock doapplications.md(whitelist de estados viastates.mjs, passthrough de--dry-run/--note, 502 fail-soft com detalhe sanitizado, spawn com array de argv). O sucesso atualiza a linha in place (classe de tom + contagens das tabs, foco preservado); a falha reverte e mostra um toast. As linhas que o relay não consegue endereçar — um status desconhecido editado à mão, um sentinel de backfill#— mantêm o badge somente leitura (correções route-review LOW; revisor: sem achados HIGH/MED). - Avisos do servidor visíveis em toda página de IA —
evaluate,deep,auto-pipeline(página e modal),career-plan,market,cv-studio(humanize + tailor) agora renderizam o arraywarningsdo servidor (truncamento de tokens de saída, drift de idioma, correções de data) como uma faixabadge-warn(role="status"); o modal do auto-pipeline não descarta mais os avisos do frame done. Nova chavellm.truncatedNotice×19. - Onda de cobertura (+111 tests) —
routes/map.mjs100/94.9,geocode.mjs96.3/92.9,content.mjs99/84.9,networking.mjs96.4/89.1,sources/habr.mjs100/98.2 (novostests/cov-*-routes.test.mjs×3,tests/sources-habr.test.mjs); o piso de branches se mantém em ≥ 90 %. - Pacote de fechamento das Linear CAR-191…216 (
docs/reviews/2026-10-30-linear-car191-216-closure-bundle.md) — fechamento pronto para colar para o dono, com SHAs de commit por CAR e comentários de evidência.
Corrigido
- Fonte de scan Trudvsem — uma página vazia (
results: {}, também “depois do fim”) não mata mais o scan inteiro (zero linhas, limpo); envelopes de erro da API (HTTP-200 comstatus: 500) lançam com o texto da própria API; a paginação caminha por offsets de registro (antes índice de página — páginas duplicadas em silêncio, ~52 vagas em vez de centenas); o caminho para antes da zona de falha de deep-offset da API (offset × limit ≥ 10000). Verificado de ponta a ponta ao vivo. - habr — títulos/empresas são limpos de tags depois da decodificação de entidades (paridade com hh.mjs): um
<script>no título de um card não pode mais chegar às linhas do scan como markup vivo;>>legítimos em títulos sobrevivem. - PUT /api/profile (caminho raw) — um bloco
candidate:semfull_namenão vazio é recusado, na mesma linha do caminho de merge de campos (antes persistiafull_name: null). - Veracidade dos hints —
.docsai da lista de aceitação de upload de CV ecv.uploadHint×19 (o parser nunca o suportou);config.openaiModelHint×19 nomeiagpt-5(o servidor mapeia para ele qualquer id*-codex);config.anthropicModelHint×19 e o default do Anthropic agora espelham os tiers do pai — defaultclaude-sonnet-5-5, premiumclaude-opus-5-5. - Link da documentação do Claude Code →
code.claude.com(a URL antigadocs.anthropic.com/en/docs/claude-codelançava TypeError no gate de links). - help ×19: o bullet de densidade de linha sumiu (o toggle deixou a UI na v1.263.0) e 18 famílias de spans
**bold**quebrados foram reparadas — mais a classe de leak do renderizador corrigida ×19 (segunda linha em branco depois de toda tabela-antes-de-parágrafo; o glifo de pipe fora das células de negrito): 0**literal no render nos 19 bundles de help.
Notas
- O modelo default do Anthropic mudou para
claude-sonnet-5-5(o tier padrão do pai). Deploys que dependiam do antigo default silencioso (claude-sonnet-4-6) sobem automaticamente — fixeANTHROPIC_MODELno.envpara ficar de fora. - Deliberadamente não feito: os dois detalhes LOW da revisão ficam abertos de propósito (o select inline não espelha a degradação
movesReadydo kanban — o toast honesto em toda falha é o comportamento escolhido; o branchcode: 'timeout'continua coberto pelo contrato do fake-writer, não por um teste de >30 s). CAR-141 (vídeo de demo) continua sendo do dono. - help ×19 ganhou a passada de prosa pós-release (bullet de densidade fora, classe de leak do renderizador corrigida) no
maindepois de a v1.263.0 sair — este release é a primeira tag que a carrega. - Também nesta tag: a base do chip de evidência (parsers de relatórios + selos de visualização), o runner fix-report-links (
POST /api/runners/report-links, cartão «Reparar» em#/health) e a estimativa/confirmação de custo do lote com registro de uso — chegaram ao main entre o corte da branch e a tag.
Tests 6905 → 7041 (+136) · Playwright 176 (173 pass / 1 opt-in skip) · cobertura 98.5 % em linhas / 90.1 % em branches · registro inalterado: 123 sources = 118 EN + 5 RU · 118 adapters.
[1.263.0] — 2026-10-30
Adicionado
- Camada de polimento de motion — novo
motion.css(a última folha do app): entradas de modal/popover (escala .97 + fade, 130–180 ms), spring-in de toast + estado suave de saída, spring de pressão do theme-toggle, escala .97 na pressão de chip/tab, infraestrutura de stagger (passos de 50 ms, teto 12), fade.page-enterna troca de rota (router), transições de halo de foco em chips/tabs. Toda regra é segura comprefers-reduced-motion(o movimento cai para none; opacidade e cor permanecem). - Correção de toque — 68 regras de hover-lift estavam sem guarda: dispositivos de toque mantinham um card “levantado” travado depois de um tap. Todos os hovers de transform agora passam por
@media (hover:hover)(neutralizador do motion.css), e o lift de card se aplica só a cards genuinamente interativos (.card:has(a),a.card,button.card,[role=button].card) — chega de affordance falsa em cards estáticos. - A11y: todo controle tem um nome programático. O novo helper
A11yDumpnomeia todos os 16 dumps de saída LLM somente leitura; 12 campos só com placeholder (CV Studio ×6, config ×2, busca do scan, select de score do tracker, nota de outcome, editor de plan, URL do auto, bug report) ganharamaria-labels; o gatea11y-form-wiresagora exige isso para a classe inteira (antes 26 sites sem nome, agora 0 + allowlist com razões documentadas).
Corrigido
- #/scan: o header sticky da tabela não pinta mais por cima da busca da topbar depois de rolar para baixo dele (o z era igual ao da topbar e o DOM posterior ganhava — agora derivado de token, abaixo dele); os inputs de “Зарплата от/до” voltam ao tamanho normal (uma regra flex de
.v2-scan-bar .inputvazava para o flex de coluna do popover e punha flex-basis 200 px como ALTURA — agora com escopo>+ guarda de popover); o botão de alternar densidade é removido por decisão do dono (a infraestrutura fica, chaves i18n removidas ×19). - Endurecimento do deploy workflow (F1–F6): a input
provideré validada por charset antes de qualquer interpolação no shell; os diagnósticos do hermes redigem valores (filtro de chaves case-insensitive + máscara de valores + corte em 80 caracteres nos três sinks,?token=mascarado também); a etapa do hermes respeitainputs.app_dir; public_url com gate https; a guarda anti-downgrade tem 6 pins executáveis (sem defaults, ordem guarda-antes-do-Deploy, regex de refs estrita). - Cauda de revisão, red-first: o round-trip da barra invertida do import de CSV (re-importar deduplica de novo), strip de
<head>do cv-voice 4827 ms → 13 ms,statedYearsMincomputado lazy, TOCTOU da captura do posting-guard, wildcard CN do MiniMax, skip de tokens deel, guardas de tamanho do picker de import antes de ler. Modal de import: nav-guard armado, input de arquivo removido no cancel, leitura de duplicatas com guarda,numvia reduce. - Lote UX do dono: ritmo vertical do hero do dashboard (os filhos de nível inline estavam colados numa única line box); deslocamento de −8 px da linha ativa do TOC de help (calha inline por linha + coluna de número); drawer mobile (fechar ✕ visível, reset de scrollTop, o fade fantasma de –paper sob guarda
.has-hud); a página de docs-assistant não transborda mais com uma URL longa numa resposta (cadeia demin-widthdo grid +overflow-wrap: anywhere); «Недавние» explicado (hint) + limpável; o Save do career-plan rearma depois de uma carga falha; o prefill de URL do evaluate não queima mais uma chamada de LLM no placeholder de colar; o Enter do auto-pipeline respeita a composição IME. - Contraste (auditoria WCAG, 296 pares): gradiente do docs-fab 2.43 → 6.4:1, toast.success → par ok-soft (1.75 → AA no dark), btn-dark do banner → virada para
--ink, variantes claras de scan-logbtn/reposts-badge/fab-chip/close, e bordas de controles de formulário a 3:1 (--cv3-input-line, WCAG 1.4.11 — antes 1.2:1). - Varredura visual: o estado vazio do tracker é um card de largura total (antes era cortado dentro da tabela de 760 px a 390); a linha do console do scan elipsifica em vez de cortar pela metade; o FAB flutuante de chat não cobre mais conteúdo a 390 (alvo de 44 px, inset 12); o estado vazio «Application statuses» do dashboard segue o padrão v2-empty; o hint «?» do stats ganha um divisor + alvo de 44 px; a tab Input do career-plan explica onde o resultado aterrissa; markdown do §1 do help (18 spans de negrito quebrados).
Alterado
- Azul de destaque → vermelho carmesim (pedido do dono, coerente com o logo, hue 15) — 5 tokens cv3 × 3 blocos de tema; o texto da bolha de chat do
docs-assistantanda sobre--accent-ink(antes #fff literal, 2.39:1 no dark); o wash do funded anda sobre--accent-soft. Danger fica no hue 25 com os próprios tratamentos. - Docs: contagem da tabela de testes do README ×17 (um drift da era v1.248), §1 do help + 18 spans de markdown, «118» do help fr/it/ta, preços de vendors CHECKED_ON 2026-10-30, fatos de HANDOFF/CONTEXT/TRACEABILITY.
Notas
- Deliberadamente não feito: o rework da varredura de skeletons fica de fora (o contrato car112 fixa o fade atual ao pé da letra); o crossfade do ícone do theme-toggle continua sendo um swap de
display(o contrato Playwright do theme-toggle o observa); a escala de.btn:activenão foi duplicada (o app.css é o dono); o stagger de motion é só infraestrutura — os tiles do dashboard o adotam depois; a prosa do help ×19 (menção de densidade, markdown do §1, «118») pega carona no próximo fan-out. - Evidência remote-QA completa: spot do ja verde (376 s / A–G ✓) na v1.262.4; en/it verdes antes, na era token-dense.
Tests 6869 → 6905 (+36) · Playwright 176 · cobertura 98.4 % em linhas / 89.9 % em branches · registro inalterado: 123 sources = 118 EN + 5 RU · 118 adapters.
[1.262.4] — 2026-10-30
Corrigido
- ja entra nas locales densas em tokens de avaliação (
ja→ o teto de 32768 tokens + o relógio de 480 s). A re-execução pontual de 5 locales no prod v1.262.3 separou os quatro timeouts502 · 300 s · 0 chda noite em transitórios e deterministas: ar (250 s), ko (291 s) e zh-CN (259 s) passaram nas suas re-execuções, o drift de linguagem pontual do ru não se repetiu — mas ojabateu no teto padrão duas vezes com zero saída (a execução completa ×19 40981578549 e a pontual 41012725839). A mesma classe de forma de it/pl. Pin red-first:evalMaxTokens('ja') = 32768,evalTimeoutMs('ja') = 480_000, as demais locales mantêm 300 s.
Notas
- Deliberadamente um patch de propósito único: a correção do
jaé a única mudança que esta versão traz — não empacota nada além disso. ar/ko/zh-CN ficam no teto padrão pela evidência desta noite (passam; as falhas da noite foram transitórios de carga do provider), e o drift do ru foi um flake de geração pontual.
Tests 6868 → 6869 (+1) · Playwright 176 · registro inalterado: 123 sources = 118 EN + 5 RU · 118 adapters.
[1.262.3] — 2026-10-30
Corrigido
- pl entra nas locales densas em tokens de avaliação (
pl→ o teto de 32768 tokens + o relógio de 480 s). A remote-QA completa no prod v1.262.1 pegou a avaliação polaca morrendo no teto padrão —502 · openrouter · 300 s · 0 ch— e a re-execução pontual despachada com a v1.262.2 reproduziu exatamente (execuções 40960568766 e 40968958062): 18/19 locales passaram A–G,itterminou em 302 s dentro do relógio token-dense de 480 s, eplbateu no muro duas vezes com zero saída. Um timeout determinista, não um flake — a mesma classe de forma que moveu oitna v1.262.1. Pin red-first:evalMaxTokens('pl') = 32768,evalTimeoutMs('pl') = 480_000, as 18 locales padrão mantêm 300 s.
Notas
- Deliberadamente um patch de propósito único: a correção do
plé a única mudança que esta versão traz — não empacota nada além disso; o conteúdo da cauda de revisão da v1.262.2 saiu separadamente.
Tests 6867 → 6868 (+1) · Playwright 176 · registro inalterado: 123 sources = 118 EN + 5 RU · 118 adapters.
[1.262.2] — 2026-10-30
Corrigido
- Cauda da revisão da onda — 7 achados de baixa severidade, cada um red-first. O round-trip da barra invertida do import de CSV: um
\numa célula era gravado dobrado e relido dobrado, então re-importar o mesmo CSV perdia a dedup empresa+cargo e podia criar uma linha duplicada — o leitor agora desfaz o escape de\\depois do split (o round-trip gravação→leitura é sem perdas, o re-import deduplica). O strip do<head>do cv-voice era quadrático em tags não fechadas — 4827 ms → 13 ms na entrada de 64 KB que a rota limita.statedYearsMinrodava o parser de anos completo para cada vaga de cada fonte mesmo quandoyears_minnão estava configurado — agora lazy, os segundos de CPU por scan grande desapareceram. Uma captura deletada entre readdir e statSync derrubava a listagem do posting-guard (TOCTOU — arquivos desaparecidos são pulados). O padrão CN do MiniMax casava apenas comapi.minimax.cnexato — qualquer URL base*.minimax.cnagora recebe o modelo CN. Tokens$do Deel que não são refs hex não vazam mais para o snippet como literais. O picker de import checafile.sizeANTES defile.text()— o teto de servidor de 512 KB respondia 413 só depois de o navegador ter parseado um arquivo possivelmente enorme — com um toastimport.tooLargelocalizado ×19. - Endurecimento do deploy workflow (revisão de workflows F1–F6).
providerera a única input interpolada no shell remoto sem validação de charset — um'no valor quebrava o quoting e executava código arbitrário no prod; agora em allowlist^[A-Za-z0-9_-]+$antes de qualquer interpolação, e o grep da guarda de chave não pode mais dar falso-positivo. A etapa de diagnóstico do hermes imprimia journalctl bruto + dumps de unit no log público; seu filtro perdia*_API_KEY=em maiúsculas e não mascarava nada — agora uma redação compartilhada case-insensitive + mascaramento de valores + truncamento em 80 caracteres nos três sinks, query strings?token=mascaradas também. A etapa do hermes ignoravainputs.app_dire tinha/opt/career-ops/src/.envhardcoded.public_urlchegava ao curl sem checagem de https (injeção de opção via um-inicial). E a guarda anti-downgrade — o fix do incidente v1.238.0 — não tinha gate executável: seis novos pins no ci-workflows (refs sem defaults, a guarda roda antes do Deploy, regex de refs estrita). - Cauda do import-modal (revisão SPA). A modal arma o mesmo nav guard da modal de outcome — navegar para longe não a deixa mais órfã sobre outra view. O input de arquivo oculto é removido no
cancel, não apenas nochange— descartes repetidos não vazam mais inputs no document.body.plan.duplicatesé lido pela forma protegida na pré-visualização. A alocação denumdo tracker usareduceem vez deMath.max(...spread)— o spread bate no limite de argumentos perto de ~100k linhas.
Alterado
- Docs: a bullet «118 EN adapters» do guia de ajuda agora carrega a contagem em fr/it/ta (as outras 15 locales já tinham). Preços de fornecedores no cvstart.org reverificados contra as páginas de preços oficiais — os quatro inalterados, CHECKED_ON → 2026-10-30. Uma varredura de drift pós-release corrigiu 42 linhas de contagem/versão desatualizadas em README ×19, CONTEXT.md, CLAUDE.md e os manuais SDD (sobras da era 109/104 e da era v1.262.0).
Notas
- Não-ação deliberada: o
window.confirmnativo do cv-studio (era CAR-179) permanece — convertê-lo paraUI.confirmé um follow-up, não um item de patch; o tooltip de frases prontas<mark title>permanece apenas tooltip (piso de a11y aceitável);remote-qa.ymlmantémcancel-in-progress: true— re-despachar substitui intencionalmente uma regressão em andamento. - remote-QA completo no prod v1.262.1: rotas ×19 ✓ · site ×19 ✓ · links ✓ · LLM ao vivo 18/19 locales A–G ✓ —
plpegou um único timeout de provedor502 · 300 s · 0 ch(território não denso em tokens; a re-execução pontual viaja com este release).
Testes 6841 → 6867 na branch de release — 6864 pass / 0 fail / 3 skip, +26 vs v1.262.1 · Playwright 176 · cobertura 98.42 % em linhas / 89.94 % em branches · registro inalterado: 123 sources = 118 EN + 5 RU · 118 adapters.
[1.262.1] — 2026-10-29
O patch de avaliação em italiano: it entra nas locales densas em tokens (teto de 32768 tokens + relógio de 480 s) depois que a era OpenRouter a pegou cortando o relatório logo antes do bloco SCORE_SUMMARY — e a ferramenta de troca de provedor que tornou o diagnóstico possível chega no deploy workflow.
Corrigido
- Avaliação em
itcortada antes de SCORE_SUMMARY (cauda do CAR-190): remote-QA 40928864980 (primeira execução com os créditos recarregados) — uma avaliação emitrodou 264 s e voltou com 15 045 caracteres etok ~15635no teto de 16 384: blocos A–G intactos,---SCORE_SUMMARY---desaparecido. A mesma classe de forma que rendeu ataseu teto em v1.261.1 (CAR-174).itentra emTOKEN_DENSE_EVAL_LOCALES(ta,hi→ta,hi,it): tanto o orçamento de 32 768 tokens quanto o relógio de 480 s passam a valer, e/api/evaluate+ auto-pipeline permanecem sobre a única fonte de verdade emllm.mjs. - Relatório em en sem blocos — um flake de geração pontual: na mesma execução uma única avaliação em
envoltou com o idioma correto mas sem nenhum dos blocos A–G; uma re-execução direcionada passou limpa (21 091 caracteres, A–G ✓). Não entra no conjunto denso em tokens — um flake não é um histórico.
Adicionado
- Deploy workflow:
mode=hermesemode=provider(cauda operacional do CAR-190):mode=hermesreinicia o gateway Hermes e imprime um diagnóstico completo (unit file com os segredos limpos, listeners antes/depois, journal do sudo, sondas por porta, a própria visão deHERMES_BASE_URLdo app, saldo de créditos do OpenRouter);mode=providertroca oLLM_PROVIDERcom uma guarda de presença de chave (recusa quando o*_API_KEYdo provedor de destino está ausente) e reinicia o app — foi assim que o prod migrou paraopenrouterquando os créditos do Hermes acabaram no meio do caminho. A guarda de refs do deploy-mode é validada apenas paramode=deploy, então os despachos de recon/verify voltam a funcionar (a mudança da era v1.261.3 de inputs obrigatórios os tinha silenciado).
Notas
- Não-ação deliberada:
ennão entra no conjunto denso em tokens — um relatório sem blocos é um flake de geração, não um histórico de volume. - Não-ação deliberada: a diretiva de idioma reforçada do ta não se estende ao
it— nenhum desvio de idioma foi observado para o italiano. - Não-ação deliberada: gravar o novo vídeo demo da UI-v2 continua com o dono (CAR-141) — a landing agora incorpora via
youtube-nocookie.comde qualquer forma. - Testes 6841 → 6841 na branch de release.
[1.262.0] — 2026-10-29
O minor de recursos upstream: o board de vagas Deel entra no scanner (registro 123), o CSV de outro tracker é importado direto no #/tracker, a verificação de integridade do JD do posting-guard e o cheque de voz do CV chegam como relays/lints, o scanner ganha um filtro de anos de experiência, e os botões de Apply em mais sete idiomas deixam de parecer ausentes — além do modelo padrão aposentado do MiniMax ser substituído e os reposts deixarem de ser fabricados entre fontes.
Adicionado
- Fonte do board Deel (CAR-184): registro 123 fontes = 118 EN + 5 RU · 118 adaptadores — detecta automaticamente boards de tenants
jobs.deel.com/<slug>(Klarna e outros); o payload flight do Next.js traz o inventário inteiro numa única requisição (títulos, localizações, arranjo, datas, descrição), o caminho/api/proibido nunca é tocado, e um tenant que publica carreiras em outro lugar responde com um redirect que a fonte recusa pelo nome; a compensação fica deliberadamente sem mapear (valores sem intervalo de pagamento seriam um chute); portões de contagem ×5 + ajuda §17 ×19. - Importação CSV do tracker (CAR-181):
POST /api/tracker/import-csvcom pré-visualização de dry-run e um commit travado — aspas RFC-4180, datas em formatos ISO / dia-primeiro / nome-de-mês, estágios de trackers estrangeiros dobrados pelos estados canônicos (um estágio desconhecido aterriza como Evaluated com uma nota, nunca descartado), dedup por URL de vaga normalizada lida da célula do link markdown ou da coluna Notes, limites de 512 KB / 2000 linhas;#/trackerganha um botão Import CSV com modal de pré-visualização, i18n ×19. - Relay do posting guard (CAR-182):
POST /api/runners/posting-guard— o gate determinístico e sem LLM de integridade do JD do projeto pai, resolvido por número de relatório pela regra de prefixo das capturas dejds/(com padding ou sem, comparado como inteiro) ou um caminho sanitizado explícito; o filho recebe apenas argv, um teto de 30 s e um contrato fail-soft; uma ação «Posting guard» em#/reports/:slugrenderiza as constatações, i18n ×19. - Cheque de voz do CV (CAR-188): 27 frases prontas de currículo (
passionate about,proven track record,leveraged,spearheaded,delve…) mais heurísticas de travessão (um intervalo de anos como 2022–2024 não é um sinal;20–30%é) como umPOST /api/cv-studio/voice-checksomente leitura e um cartão#/cv-studioque destaca as ocorrências exatas; a checklist do Tailor cresce para seis invariantes; i18n ×19. - Filtro de anos de experiência do scan (CAR-180): o parser jd-years (65 formulações, nunca descarta quando não tem certeza) lê o mínimo declarado nas descrições das vagas, uma nova opção
years_min:do portals pula vagas sem qualificação suficiente comoskipped_experience(um status de histórico observacional que nunca fixa uma URL), eyearsMinsegue no snapshot do scan para uma UI futura. - Controles de Apply em mais sete idiomas (CAR-185/189): vietnamita
Nộp đơn ứng tuyển, búlgaroКандидатствай/Кандидатстване/Външно кандидатстване(o substantivo ancorado ao início do rótulo — links de artigos de conselho não são Apply), holandêsSolliciteer/Solliciteren, espanhol¡Apúntame!/Postularse(rótulos, não o verbo — links de FAQ deixam de importar), chinês申请职位/投递(ancorado ao controle inteiro) — vagas ativas nesses boards deixam de ser lidas comono_apply_control.
Corrigido
- Modelo padrão do MiniMax (CAR-187): o
MiniMax-Text-01aposentado como padrão é substituído porMiniMax-M3.1-Flashemapi.minimax.ioeMiniMax-M3emapi.minimax.cn; a URL base fica presa ao fornecedor (um host fora do fornecedor é recusado em runtime e a chave nunca chega até ele); a dica de configurações ×19 nomeia os novos padrões. - Reposts exigem a mesma fonte (CAR-186): um cargo listado no LinkedIn e no Greenhouse do empregador não é mais reportado como repost — os clusters agora se dividem por
sourceHost(), que dobra subdomínios regionais apenas em sites conhecidos (de.linkedin.com≡www.linkedin.com, masca.example.comfica separado), dobra os aliases de host do Greenhouse numa única fonte e remove um ponto final. - Desvio de idioma nas avaliações em tâmil (CAR-183): uma diretiva de tâmil reforçada agora senta na cauda volátil do prompt junto ao orçamento de volume (o slot do CAR-174) — os relatórios do remote-QA voltam a aterrizar em tâmil após o desvio intermitente visto na v1.261.2.
Notas
- Não-ação deliberada: o relay do posting-guard chega em modo fail-soft — o fork ainda não carrega o
posting-guard.mjsdo projeto pai (o PR upstream #6146 segue aberto), então o endpoint responde{available:false, reason:"script-not-found"}até um sync do pai o entregar. - Não-ação deliberada:
yearsMinnão aparece como chip de UI em#/scanneste release — o campo vai no snapshot e o filtro existe apenas na configuração de portals. - Não-ação deliberada: as mudanças de Machine Summary em modes/reports upstream (#6161/#6160/#6157) não são portadas — chegam com o projeto pai implantado, não como mirrors do web-ui.
- Testes 6734 → 6841 na branch de release; a chave de dedup do scanner fica intocada (o comportamento de normalização de URLs não mudou).
[1.261.3] — 2026-10-28
O patch de conclusão de design: fase 3 do design do Lovable (densidade + aposentadoria completa do coral), o pool de hosts do scan (32 empresas, 10 por host), seis correções de localização de providers upstream, a fonte Trakstar Hire (registro 122), desfazer + guarda de alterações não salvas no CV Studio — mais as correções P3 da regressão final e a paridade de docs.
Corrigido
- Rótulo «related» do cluster do mapa 3.16:1 → 4.68:1 (ambos os temas): o
--map-score-midclaro foi escurecido para#567b75(o#5f7f7asugerido media apenas 4.37 — foi necessário um passo mais escuro); o lado escuro já estava em 4.98:1, intocado. Fixação vermelho-primeiro emmap-cluster-visual. - Anel de foco do skip-link: o último contorno literal
#ff385c→var(--accent-c)— todos os 78 anéis de foco agora seguem o token de acento. - Topologia de acento de
.tab-btn.is-active(#584, fase 3): o controle misturava três famílias de cor (lavagem coral + texto danger + borda azul); agora é um único par accent-soft. - Correções de localização de providers upstream ×5 (#580, CAR-176): flag
Fully Remotedo workday (não é um lugar), fan-out de telecommuting do workable + state-only-when-cityless, vírgula à direita do successfactors, fronteira de palavra para remote no lever, rótulos com prefixoLocationno icims. - http-json: sem retry num timeout gasto (#580) — um abort por deadline não é transitório em ambos os helpers de retry (o upstream mediu ~94s num board Ashby a 30s×retries).
- Paridade de docs (#587): os últimos contadores da era 17/18 em HANDOFF/CONVENTIONS/README (uk ganhou sua seção Локалізація que faltava; o histórico de § estendido até §32/§33 — aritmética de 33 H2 verificada).
Adicionado
- Fase 3 do design do Lovable (#584): tokens de densidade ativos — linhas de tabela ≈32px, controles 30px, chips 24px (exceção de espaçamento WCAG 2.5.8); todo resíduo rgba coral movido para pares cv3 (
.dash-hero,.badge-bad, halos,.tab-btn.is-active);--ease-outdeclarado, TOKEN_HANDOFF vazio; contrato.callout--ok/--danger. - Fonte Trakstar Hire (#583, CAR-177): registro 122 fontes = 117 EN + 5 RU · 117 adaptadores — jsapi.recruiterbox.com com host fixado, percurso por offset com paradas curtas/vazias/repetidas, parciais mantidos, marcação
trakstarTruncated; portões de contagem ×5 + ajuda §17 ×19. - Pool de hosts do scan (#579, CAR-178): até 32 empresas em concorrência, limitadas a 10 por host (padrão keyed-limiter do upstream) — snapshot byte-idêntico à execução sequencial (portão vermelho-primeiro com mock de timing).
- Desfazer + guarda de alterações não salvas no CV Studio (#582, CAR-179): pilha de undo limitada (30) sobre resultados de execuções de IA com
Cmd/Ctrl+Zseguro para layouts não-QWERTY, guarda de alterações não salvas ao sair da rota (live-probe dirty, confirm/rewind/beforeunload), i18n ×19. - Correções de providers upstream testadas ×17 (parte do CAR-176); o resumo do remote-QA nomeia as fontes de scan com falha +
tok ~Npor eval (#567, já na v1.261.2 — a observabilidade foi usada para a triagem desta release).
Notas
- O acento agora é azul (conceito do Lovable): ações primárias/estados ativos/anéis de foco seguem
--cv3-accent; o vermelho fica reservado para danger (.btn-danger,toast.error, texto de danger). O coral sobrevive apenas no asset PNG do logo (decisão do dono). - Densidade: linhas de tabela ≈32px / controles 30px / chips 24px — exceção de espaçamento WCAG 2.5.8 documentada; a canary de 44px da v1.26.1 foi reescrita sobre o contrato de tokens.
- CodeQL: todos os 10 alertas abertos fechados (4 descartados como FP com justificativa: classes documentadas llmRateLimit/atomicWrite; 6 corrigidos na fonte).
- Testes 6655 → 6734 na branch de release; nenhum comportamento de fonte do scanner mudado além da nova fonte Trakstar.
[1.261.2] — 2026-10-28
O patch de estabilidade + polimento: o cache de geocoding sobrevive a um crash no meio da escrita (CAR-173), o UI.md renderiza continuações de bullets e listas aninhadas, os vazamentos de chaves no texto renderizado dos bundles de ajuda são fechados ×17, o evaluate ganha um teto de tokens por locale para ta (CAR-174), o chrome RTL espelha via propriedades lógicas (85 achados), as capturas do mapa são reenquadradas ×19 e os clusters do mapa passam no contraste no tema escuro — mais a primeira fase da integração de design do Lovable (folha passiva tokens-v3.css), backfill de docs (revisão de release + specs) e isenções de cobertura para variância de node do CI.
Corrigido
- Perda por escrita rasgada no cache de geocoding (CAR-173, #562): ambos os caminhos de flush (insert-flush com debounce, exit-flush) gravavam
.cache/geocode.jsoncom umwriteFileSyncpuro — truncate-then-write — então um crash, OOM ou SIGKILL no meio da escrita deixava um arquivo rasgado e oJSON.parsedo próximo boot lançava erro, descartando silenciosamente o cache persistente inteiro (semanas de orçamento do Nominatim), e não apenas o do dia. Ambos os pontos de escrita agora passam porfile-lock.mjs::atomicWrite(temp no mesmo diretório → rename → unlink em caso de falha) — o mesmo contrato que FULL-R1/FULL-M1 aplicaram apipeline.md,cv.md,profile.yml,career-plan, entrada do batch e memory. A própria maquinaria de flush do CAR-142 (insert-flush com debounce, exit-flush, shutdown limitado) foi verificada intacta vermelho-primeiro: os testes (a)/(b) travam que inserções chegam ao arquivo dentro da janelaGEOCODE_SAVE_MSe que ele permanece JSON válido; (c) é um portão de mecanismo mais execuções comportamentais de ambos os caminhos de flush afirmando a ausência de lixo de temp e um arquivo parseável. - Continuação de listas no UI.md (#563): o handler de listas só consumia linhas consecutivas
-/*, então uma linha de continuação indentada após um bullet caía fora do<ul>emitido e a passagem de parágrafos pulava o bloco — a continuação vazava como prosa crua com marcadores literais**/backtick (~95 ocorrências soltas por locale nos bundles de ajuda; en.md 95, ru.md 104). Uma linha de continuação — whitespace à esquerda, não um novo bloco (heading, bullet, placeholder de fence com prefixo NUL, blank) — agora se junta ao<li>anterior como texto unido por<br/>, cominline()rodado por linha para que marcadores de ênfase nunca formem pares através da junção; a guarda de placeholder de fence é pelo primeiro caractere NUL, não por casamento literal de token. Bullets-aninhados, listas numeradas, fences dentro de listas e headings dentro de listas permanecem uma lacuna separada documentada (próxima onda de docs). - Vazamentos de chaves no texto renderizado da ajuda ×17 (#561): o remote-QA encontrou 85 chaves i18n cruas visíveis na ajuda renderizada (causa raiz comprovada por repro: o mesmo consumo de bullet de linha única do UI.md — uma continuação quebrada emitida como texto cru mantinha seus backticks literais; as seções de ajuda da v1.260/261 escreviam bullets multilinha). 163 bullets desdobrados para uma linha através de 17 locales — apenas whitespace, nenhuma palavra traduzida foi tocada (velho-vs-novo verificado). O novo portão
tests/help-rendered-keys.test.mjsrenderiza cada bundle pela cadeia real (stripGithubOnlyBlocks+UI.mdcarregado via vm) e falha se qualquer uma das 1.711 chaves aparecer no texto; vermelho-primeiro 17 locales → verde. O ferramental de repro vem no repositório:scripts/remote-qa/help-render-scan.mjs(vm) +help-render-crosscheck.mjs(DOM real). - Remote-QA Ctrl+K verifica o contrato da paleta do CAR-122 (#561): o
prod-regression.mjsagora espera a paleta de comandos após Ctrl+K (.nav-v2-palette[role=dialog]+ foco emnav-v2-input) OU o foco na busca legada como fallback, em vez de aceitar silenciosamente qualquer um; o teste unitáriotests/remote-qa-ctrl-k.test.mjstrava 6 cenários num DOM simulado, vermelho-primeiro 0/6 → 6/6. - Reenquadramento das capturas do mapa ×19 (#560): report do dono sobre
images/job-map-en.png— metade da busca do topbar + um h1 cortado no topo, uma fatia cinza da lista lateral na borda direita, um cluster de marcadores cortado pelo quadro perto de Londres e uma linha branca horizontal cruzando o mapa a ~2/3 da altura. Ocapture-map-screenshots.mjsagora espera o dreno da fila de geocoding (located + noLoc === total, não o contador N/N — linhas Remote são estruturalmente sem local, então a espera antiga nunca poderia completar), escondeheader.topbare#notif-drawerpara o shot, recorta a caixa exata de.job-map-page(nenhum painel cortado pela borda do quadro), dá dois passos de zoom out para que nenhum cluster fique meio cortado, fixa a altura do mapa e tira um screenshot simples da viewport (captureBeyondViewportreamostra a camada de tiles composta e pinta faixas brancas nas fronteiras de linha de tiles) e alinha o container do mapa por inteiros. Todas as 19 capturas job-map refeitas. - Bolhas de cluster do mapa — contraste no tema escuro + ajuste de rótulo (#572): varredura do dono P2/P3 — os anéis de cluster no tema escuro ficavam sobre um preenchimento branco fixo (1.83:1); os anéis agora usam
var(--paper)com dígitos da paleta de score (medidos 4.98:1+, preenchido 9.53:1; a faixa mais baixa é matematicamente incolorível no escuro e mantém 6.1:1 via um caminho honestodata-dim), e o rótulorelatedcabe em sua bolha (font-fit via rAF, números nunca encolhem). - Troca de idioma no #/scan — rearmamento de skeletons (follow-up do #534, agente em voo, pousa antes da tag): follow-up da correção do dono na v1.261.0 (#534) — os skeletons rearmados num repaint de troca de idioma não sobrevivem mais a um refetch completado.
- Drift de docs (CAR-139, agente em voo, pousa antes da tag): contadores do README ×19, HANDOFF ×19 e fatos do CONVENTIONS ressincronizados com o estado vivo do registro e dos testes.
Adicionado
- Revisão de release + backfill de specs (docs, #559/#558):
docs/reviews/REVIEW-2026-10-28-v1.261.1.md(a onda v1.261.0/v1.261.1 revisada contra suas specs) e o backfill de specs SDD para a mesma onda — o final do BACKLOG agora nomeia a lacuna restante (testes dedicados parasources/habr.mjs). - Varredura profunda RTL (#571): o harness AR percorre 39 rotas × LTR-vs-RTL (espelhamento em X, overflow, clipping, assinaturas de text-align) — 85 achados corrigidos: o chrome fixo (toast, sidebar, drawer + seu × de descarte, docs-FAB, usage-HUD, skip-link) movido para
inset-inline-*/border-inline-*, as tabelas paratext-align: start/endem 17 arquivos de view + 2 libs, o[dir=rtl] text-align:rightgeneralista removido (brigava com a centralização da coluna de estrelas do scan), o isolamento da coluna de score do CAR-58 movido para um spanltrNum. - Harness de a11y de teclado (#570):
tests/playwright-a11y-keyboard.mjspercorre 11 rotas (ordem/armadilhas de Tab, indicadores de foco, overlays com Escape, Enter/Space) — 0 defeitos de produção; a cobertura de regressão é nova. - Varredura de não-traduzidos i18n (#565): 36 valores idênticos ao en traduzidos ×9 locales (
*.rolePh, chaves de config, manifesto ta) + uma guarda de varredura com allowlist fechada; auditoria i18n do site (cvstart.org) (#568): 20 chaves × 18 locales traduzidas (o bloco inteirodemo.*/stats.t.*/showcase.tab*estava em inglês em toda parte), 1 chave morta removida ×19. - Observabilidade do remote-QA (CAR-175, #567): o resumo nomeia as fontes de scan com falha (
stderr samples, redact-before-truncate) e imprimetok ~Na partir do uso dos providers; a lógica vive numsummary-parts.mjspuro com um portão de drift. - Listas aninhadas de marcador no UI.md (um nível, #564): bullets
-renderizam como um<ul>aninhado (seguro para placeholder de fence) — as últimas 2 ocorrências soltas de prosa por locale acabaram. - Integração de design Lovable — fase 1 (#566) / fase 2 (branch, pousa antes da tag):
public/css/tokens-v3.cssporta o conceito do Lovable verbatim (superfícies oklch 0–3, pares de tinta anotados com AA, família de acento, ok/warn/danger/info/neutral soft+ink, bandas de score A–G ×2 temas, densidade + foco + sombras); a fase 2 o ativa sobre os nomes de token existentes (acento dividido blue/danger, bandas de score + callouts nos tokens cv3) com os portões de contraste/role/dark atualizados. - Teto de tokens por locale no evaluate (CAR-174, #569):
evalMaxTokens(lang)— ta/hi pedem 32768 (os três clientes SDK re-clampavam em 16384; ambas as camadas corrigidas), mais um orçamento de volume de tâmil no prompt (≤5 frases por bloco, ≤900 palavras) — o relatório ta do remote-QA da v1.261.1 foi cortado no limite de tokens de saída (faltando Blocos B–G + SCORE_SUMMARY). - Follow-through de correções reais do CodeQL: o novo ferramental de render da QA substituiu o tratamento manual de entidades por passes de split estruturais +
htmlToText({cap: Infinity}); asserções de redact travam a saída mascarada exata; constantes não usadas do harness RTL removidas. - Política de isenção de cobertura para variância de node do CI (habr #558, states #561):
sources/habr.mjs(branch no matrix de node do CI 87.23 vs local ≥89) estates.mjs(CI 86.49 vs local ≥89) entram para as isenções emscripts/coverage-baseline.json— arquivos cuja cobertura de branch medida no CI fica estruturalmente abaixo do piso local por causa da variância de versão de node são isentados em vez de rebaixar o portão inteiro.
Notas
- Contrato do Ctrl+K (CAR-122): o atalho abre a paleta de comandos — NÃO foca diretamente a caixa de busca; a busca é focada a partir da paleta. A regressão de prod do remote-QA agora verifica exatamente isso (#561).
- Descartes de FP do CodeQL ×5: os alertas
js/missing-rate-limitingna main aguardam o tokensecurity_events— ação do operador, não uma mudança de código. - Pousou após o corte da branch: #561/#562/#563/#564/#565/#566/#567/#569/#570/#571/#572 estão todos mesclados na main; os agentes de #534-skeleton e CAR-139 mesclam antes da tag. Listas aninhadas de marcador além de um nível e geometria de views pesada em inline permanecem lacunas documentadas.
- Testes 6609 na branch de release (+15 desde a v1.261.1; ~13 mais do #561 no merge — 2 novos arquivos de portão); os únicos testes vermelhos pré-fan-out são os portões de paridade CHANGELOG ×19 (o fan-out de locales é o próximo passo do orquestrador); nenhuma fonte do scanner tocada (registro 121 = 116 EN + 5 RU · 116 adaptadores).
[1.261.1] — 2026-10-28
O patch de cliente da QA em produção: uma correção de crash P1 no #/two-pager, o Ctrl+K funcionando em layouts não-QWERTY, a onda mobile de 390px (overflow do docs-assistant, sobreposição do chip do mapa, um harness de 39 rotas), a conclusão do CAR-137 (erros específicos, v2empty ×5, hints ×13 + páginas de modo) e o CAR-140 pousando screenshots v2 reais em toda parte.
Corrigido
- TDZ do two-pager (CAR-170, P1, #554):
Cannot access 'previewTimer' before initialization— o editor de tags salvas disparavaonChangedurante a construção para cada chip restaurado enquanto o loop de construção ficava lexicalmente acima dolet previewTimer, então o render inteiro do#/two-pagerquebrava (sem h1, nos 19 locales). O agendador + binding agora vivem acima do loop; um teste comportamental executa o módulo real da view — o erro exato de produção antes da correção, uma página renderizada depois — além de um portão de drift de ordem lexical. - Ctrl+K em layouts não-QWERTY (CAR-172, #554): ambos os handlers de atalho casavam apenas com
e.key— num layout russo o atalho chega comokey='л' code='KeyK'e não fazia nada. Agora casam pore.code === 'KeyK'em nav-v2.js e app.js; reproduzido num navegador real com um atalho sintético ‘л’/KeyK. O contrato do CAR-122 é reafirmado (ver Notas). - Overflow de 390px do docs-assistant (CAR-172, #554): os starter chips do CAR-136 eram
.btn(nowrap,flex-shrink: 0) — um item inquebrável de 418px empurrava o#/docs-assistant56px além de uma viewport de 390px; o padrão de encolhimento do CAR-146 (em v2-llm.css, os portões CSS de 800-LOC intocados) traz isso a 0. - Sobreposição do chip do mapa @390 (#552): numa viewport de 390px os chips meta do mapa sobrepunham a linha de CTA (map.css).
- CAR-137 — erros específicos + v2empty ×5 (#550): cinco fallbacks genéricos de erro (‘Error’ / ‘failed’) viraram chaves específicas e acionáveis — falha do POST de evaluate, stream do auto-pipeline sem evento terminal, adição scan→pipeline, carregamento de clusters de reposts, desfazer do pipeline; os últimos cinco estados vazios planos (
#/reports,#/usage,#/portals,#/activity,#/dashboard) se juntam ao padrão v2empty do CAR-124 (explicação + exemplo rotulado aria-hidden + ação pré-conectada; 15 novas chavesv2empty.*, quatro chaves mortas de uma linha removidas) — tudo ×19 dicionários, snapshot regenerado. - CAR-137 — HelpHint ×13 + kit de mode-page (#550): a hint contextual «?» agora está no H1 de toda página restante (pipeline, reports, dashboard, cv, portals, usage, activity, assessments, map, health, docs-assistant, settings) e nas 8 páginas de modo via o kit (cada cfg de MODES carrega uma
hintKey, renderizada através deHelpHint.title).
Adicionado
- Harness mobile-390 (#552): uma varredura Playwright de cada rota do SPA (31 canônicas + 8 páginas de modo = 39 hashes) a 390×844 com um corpus semeado — verificação de overflow horizontal por rota (scrollWidth vs clientWidth, tolerância de 1px, nomeia o maior culpado) mais uma verificação de hit de CTA (nenhuma barra sticky/drawer/FAB cobre um CTA primário); opt-in, skip gracioso sem binário de navegador, sem rede.
- Capturas v2 frescas ×48 (CAR-140 fase A, #551): screenshots reais da UI v2 de um fixture CI-isolado semeado — dashboard ×19 + job-map ×19 (job-map-ta primeira aparição, job-map-vi novo) + scan/pipeline/tracker/reports × en/ru — alimentando README, ajuda e a landing.
- Screenshots reais no cvstart.org (CAR-140 fase B, #553): os slots de placeholder do CAR-140 acabaram — a landing mostra as capturas v2 reais (vitrine do job-map + linhas de screenshots, ×19 locales da landing).
- Hints do CAR-137 (#550): 21 novas chaves traduzidas ×19 (
help.hint.*×20 + ashintKeydas páginas de modo) — toda página agora se explica no lugar.
Notas
- Contrato do Ctrl+K (CAR-122): o atalho abre a paleta de comandos — NÃO foca diretamente a caixa de busca; a busca é focada a partir da paleta. A linha «Ctrl+K фокусит поиск» do checklist de QA da v1.261.0 fica substituída; o prompt de QA da v1.261.1 traz a verificação atualizada.
- Correções reais do CodeQL (#547): 4 alertas fechados (iteração de chave literal em content.mjs tornada estrutural, varredura de lint) — pousou pós-release na main da v1.261.0 antes deste patch; listado aqui por completude.
- Testes 6582 (+51); suíte de navegador 171–172 aprovados / 0 falhas / 1 skip opt-in; o harness mobile-390 roda standalone (
node tests/playwright-mobile-390.mjs). Nenhuma fonte do scanner tocada (registro 121 = 116 EN + 5 RU · 116 adaptadores).
[1.261.0] — 2026-10-28
A onda de revisão completa da v1.261.0 está concluída (todos os achados HIGH + MEDIUM pousados), a correção do alternador de idiomas reportada pelo dono, correções de qualidade de avaliação, fan-out da ajuda ×18, a landing v2 do cvstart.org — mais 4 specs SDD/OpenSpec documentando a onda. Toda correção pousou por um fix-forward vermelho→verde e uma revisão de contexto-fresco GLM-5.3-Flash.
Segurança
- FULL-R1 — portão CSRF para acting-GET + escritas atômicas e travadas do pipeline (#519): portão
Sec-Fetch-Site/Origin/Referer sobre/api/stream/*,/api/run/*,/api/geocode(ACTING_GETexportado, portão estático de cobertura); toda leitura-modificação-escrita emdata/pipeline.md/data/last-scan.jsonsobwithFileLock+ o novoatomicWrite(temp no mesmo diretório → rename → unlink em caso de falha). - FULL-R2 — cluster SSRF nas fontes (#514): rss.mjs https + rejeição de endereços privados; ~25 fontes com
fetchImplcru → transportes guardados; mirrors com host fixado; validação de redirect para habr/hh/geekjob/getmatch;delay(ms, signal)compartilhado. - FULL-R4 — corrupção de prosa no stripDangerousMarkdown (#513/#518): remoções de esquema apenas em contextos de link/atributo; entidades decodificadas em uma cópia só de detecção («JavaScript: React, Node» e «R&D» sobrevivem).
- FULL-M2 — hardening de transporte (#520):
safeGethonratimeoutMscom o signal do chamador (controlador da ponte);guardResolvedHostfalha FECHADO em erro de DNS. #525 acrescenta remoção de cabeçalhos de credencial em redirects cross-origin, desacoplamento do listener de transporte em todo caminho de encerramento e uma correção de crash com signal pré-abortado. - FULL-M4 — logo/batch (#523): o logo fixa magic bytes em TODOS os caminhos (um
image/pngmentiroso não pode carregar SVG), limita o content-type aimage/*no momento de armazenar, cache privado + nosniff; batch:--parallellimitado a 1–8,--min-scorevalidado, BATCH_BUSY single-flight,llmRateLimitem mutações de config/batch.
Adicionado
- CAR-147 — teto de avaliação sensível ao locale (#524):
evalTimeoutMs(lang)— ta/hi recebem 480 s em vez de 300 s (escritas indo-arianas tokenizam vários tokens por sílaba; a parede antiga produzia 502 + relatório vazio); o cliente do remote-QA espera 540 s. - CAR-133 — landing v2 do cvstart.org (#532): hero com parallax gated por reduced-motion, uma demo SIMULADA claramente rotulada do fluxo scan→evaluate→tracker, seções com scroll-reveal e contagens verificadas ao vivo, slots de placeholder de screenshot do CAR-140.
- CAR-135 — ajuda reescrita para a UI v2, fan-out ×18 completo (#533, #540, #541, #542): os 19 arquivos de ajuda descrevem o shell v2 (nav colapsável, paleta Cmd/Ctrl+K, skeletons, estados vazios de exemplo+ação, chrome do scan v2, pipeline agrupado+desfazer, relatórios v2, kanban); os rótulos da UI citam suas chaves de i18n; a frase das 121 fontes vive a partir do registro.
- Specs (SDD/OpenSpec) (#535): backfill da wave-two de 27 de outubro + três specs prospectivas documentando a onda v1.261.0 (fan-out da ajuda, hand-offs de escrita, invariantes do alternador de idiomas).
Corrigido
- Alternar idioma não apaga mais o #/scan (#534) — reportado pelo dono: o estado local de scan da view (resultados, chips de facetas) agora é module-level; harness Playwright comportamental com refetch atrasado em 4 s (vermelho no formato antigo).
- CAR-148/149 — relatórios RU «Block G ausente» (#530): o prompt ensinava três mapas A–G inconsistentes; skeleton + lista + exemplo agora concordam com o oferta.md (G = Posting Legitimacy); portão de drift comportamental.
- CAR-150 — desfazer do pipeline preserva metadados de comp (#537): DELETE responde
comp, POST aceitacompopcional gated, a view carrega{token, comp}por todos os ramos de fallback. - FULL-M3 — fontes mortas reportam quadros honestos (#522): getro/mycareersfuture/meituan/mokahr/glints lançam erro em page-1 malformada (uma API morta não lê mais como «saudável, 0 vagas»);
pinnedOverridefixa os overridescompany.apide 18 adaptadores. - FULL-M5 — uma única cascata de provedor (#521): routes/llm.mjs via
runActiveProvider(+cachePrefix, signal); interceptação no subprocesso Gemini; contratos de resposta byte-idênticos. - FULL-M1 — escritas em arquivos compartilhados travadas (#526, #539):
runTrackedScript+ rosterTRACKER_MUTATING; os spawns de outcome/followup seguram a trava; tracker.mjs escreve viaatomicWrite; o PUT salva travado+atômico. - FULL-M6 — consolidação servidor + cliente (#531, #536, #525): dotenv com protótipo nulo + recusa de
__proto__; isPrivateOrLoopback cobre NAT64/6to4/benchmark/reservados; cache mtime do env-config; GC real de slots no file-lock; safeGet timeout+signal; guarda de DNS fail-closed; SSE ×4 →API.postStream; libs de foco/rótulos/status; clipboard aguardado; tint Hired no dashboard. - R3 — drift de tokens CSS (#527):
--accentresolvido (os anéis de foco do mapa estavam silenciosamente mortos); 11 durações fora dos tokens absorvidas; portão de drift. - R4 — carregamentos atrasados (#538): assessments/mode-page/preview do pipeline renderizam skeletons do CAR-112.
- Lote CodeQL + CI (#517, correção #539): imports não usados, o portão ACTING_GET importa a regex real, fatia de lifecycle re-ancorada.
Notas
- Deliberadamente não feito: pinning de DNS no momento da conexão (precisa de undici — fora das dependências, residual documentado); screenshots do CAR-140 (precisam da UI v2 implantada); CAR-137/138/141 (próxima passada de docs); a classe
js/missing-rate-limitingdo CodeQL é um falso positivo documentado (limiter customizado não creditado). - Fan-out da ajuda ×18: a wave-1 de es/de pulou a nota de introdução e o delta do card Active Companies (de pousou a própria introdução; es recebe um follow-up de uma linha).
[1.260.0] — 2026-10-26
O trem de hardening por revisão: oito merges (#491–#498) das rodadas de revisão opus-5-5 e de IA sobre a frota da v1.259.0 — normalização salarial, escopo das datas de relatório, robustez do geocódigo, cache-busting do bundle r2+r3 e a correção de overflow do deep research — mais duas UIs v2 (pipeline, relatórios). Toda correção pousou por um fix-forward vermelho→verde.
Corrigido
- Normalização da comparação salarial (CAR-143 rev-2): marcadores de período são reconhecidos apenas perto do número a que pertencem — «6 month contract, $120k» não é mais anualizado ×12, e as formas de período RU/ES que só valem anexadas («за месяц» junto ao número) vencem palavras incidentais; a família de símbolos
$/¥é reconhecida, porém não mapeada, a menos que um código ISO explícito compartilhe a linha (dólares AUD/CA/SG não são mais faturados como USD, e uma forma ¥ RMB recebe uma ressalva explícita em vez de uma conversão JPY que erra por ~20×); números soltos 19xx/20xx são sempre anos; os números de uma faixa herdam o período da outra ponta;minimumetarget_rangedo perfil nunca são emendados em uma única faixa. - Escopo do
fixReportDate(CAR-144 rev-2): a correção de datas fixada pelo servidor se aplica apenas ao preâmbulo antes do primeiro cabeçalho##(um relatório com título em H2 recebe um no-op conservador — uma data desatualizada é aceitável, uma fabricada não); dentro do preâmbulo: um candidato único é corrigido; senão um**Date:**em negrito único; senão nada (dois candidatos em negrito ou dois em texto simples não reescrevem nenhum). A trava de rótulos PDF do FIX-5 agora lê o dicionário montado real — um locale ausente lança erro em vez de passar silenciosamente por um fallback em inglês. - Chip de localização do Habr + robustez do geocódigo (CAR-142 rev-2): um chip meta do Habr vira cidade apenas com evidência estrutural (um link de filtro de cidade ou um ícone de localização) — avisos de relocação («Возможна релокация») e tipos de emprego nunca mais se passam por localizações; o cache de geocodificação agora sobrevive a um reinício (flush em
beforeExit/exit/SIGTERM+SIGINT com re-raise, o flag dirty limpo apenas depois que a escrita pousa), o desligamento é limitado (trava de exit-loop, contador de geração, LRU de recência) e um orçamento de geocódigo esgotado responde 503 + Retry-After em vez de um 502 genérico. - Cache-busting do bundle (CAR-145 r2+r3): o shell cita
/js/bundle.js?v=<content-hash>— imutável em caso de match, no-store em caso de divergência — matando a janela de 5 minutos de deploy em que um shell novo casava com um bundle antigo em cache. O hash e o stream compartilham um único descritor de arquivo (sem leituras rasgadas); uma leitura curta responde null em vez de um hash de fallback por stat que poderia envenenar um deploy inteiro; omake-bundleescreve a identidade e os companheiros .br/.gz via um temp com prefixo de ponto + rename, então um build morto não serve nem bytes escritos pela metade nem vaza seu arquivo temporário. - Overflow do deep research (CAR-146): um briefing de pesquisa salvo cujo nome de arquivo sozinho excede a viewport de um celular não empurra mais o
#/deepalém de 390px — o card se limita à própria linha, o título quebra linha e a data fica em uma única linha; a varredura de viewport estreita agora percorre o#/deepcom um fixture semeado excessivamente longo (o único achado das duas rodadas de remote-QA, fechado). - Hardening do pipeline v2 (CAR-116 review): exclusões pedem confirmação e têm desfazer (com texto de desfazer honesto), sem fabricação de empresa anfitriã nos cards, ids de linha FNV-1a, contagens verdadeiras das operações em massa e uma trava de re-entrância sobre elas.
Adicionado
- Pipeline v2 (CAR-116): cards enriquecidos, uma visão agrupada e descarte em massa com desfazer; 17 novas chaves
pipe.*distribuídas traduzidas em todos os 19 dicionários. - Relatórios v2 (CAR-118): busca ao vivo com filtros de faixa de pontuação/legitimidade/empresa/data, cabeçalhos ordenáveis (
aria-sort), uma visão de cards persistida com botões de ação por faixa, um histograma de pontuação com clique-para-filtrar e a renderização unificada «Company — Role» / «x.x/5» (window.ReportOps); 31 chavesrep2.*distribuídas traduzidas em todos os 19 dicionários.
Notas
- Toda correção passou por uma rodada de revisão com evidência vermelho→verde; os dois achados HIGH da revisão por IA no primeiro bundle r2 (hash de leitura curta, atomicidade dos artefatos companheiros) foram fechados pelo r3, e as rodadas CAR-143/CAR-144/CAR-142 re-verificaram cada uma os achados em aberto de sua predecessora.
- Deliberadamente não feito: a visão de clusters do mapa segue como CAR-125 (na fila); a restauração de metadados do pipeline no lado do servidor é um ticket separado; nenhuma correção retroativa para conteúdo salvo sob os estados pré-rev-2 da v1.259.0.
- Testes 5988 (+165); suíte de navegador com 152 aprovados / 0 falhas / 1 skip opt-in. Nenhuma fonte do scanner tocada (registro 121 = 116 EN + 5 RU · 116 adaptadores); as 48 novas chaves de i18n pousaram com seu fan-out ×19 dentro dos próprios PRs de feature.
[1.259.0] — 2026-10-25
Segundo trem da frota de agentes, seis correções: as datas dos relatórios são fixadas pelo servidor, o geocodificador do mapa faz cache e lê cidades cirílicas, a ajuda ×18 cita rótulos de botões localizados, as frases da UI param de misturar idiomas, as comparações salariais são calculadas no servidor — e o bundle JS passa a ser distribuído pré-comprimido (carregamento a frio 3.1 MB → 598 KB).
Corrigido
- Datas de relatório inventadas (CAR-101): o prompt de avaliação agora fixa a data de hoje no servidor («the Date: field MUST be exactly
— copy verbatim; never invent») e o fixReportDatereescreve uma data desviada para hoje em todos os pontos de aceitação (ramo Anthropic, subprocesso Gemini, cauda compatível com OpenAI, /api/deep, auto-pipeline), com um aviso + registro de atividade — uma correção, nunca uma rejeição. 349/789 relatórios de produção tinham datas inventadas; os novos não podem. - Geocodificação do mapa (CAR-105): as strings de cidades em cirílico das linhas do hh.ru/Habr agora chegam ao geocodificador; um cache limitado e persistente (
data/geocode-cache.json, withFileLock) garante que uma cidade já resolvida nunca consulte o provedor duas vezes; as chamadas de geocodificação têm orçamento por requisição, então o mapa se preenche progressivamente em vez de travar por 13.9 s. - UI misturando idiomas (CAR-108): 23 vazamentos por chave corrigidos em 17 dos 19 dicionários (85 valores) — «все matching», «только remote», «Открыть Scan», o funil «Evaluated → Applied…» e outros viraram frases integralmente localizadas reutilizando o vocabulário de produto de cada locale.
i18n-no-latin-leaksganhou a tabela de fragmentos + a sonda de funil (vermelho→verde). - Virada de veredito por moeda (CAR-109): a comparação salarial é calculada no servidor em
comp-compare.mjse embutida de forma canônica (Candidate minimum: … per YEAR (raw: …)vsJD offer: …); formas mensais ×12, k/к/тыс/萬 e vírgula decimal são normalizadas antes da comparação; uma conversão incerta nunca pode, por si só, virar o veredito (o caso zh-TW «€80–100k ниже минимума» está morto). O modelo nunca multiplica. - Rótulos de botões da ajuda ×18 (CAR-107): os bundles de ajuda localizados citavam rótulos em inglês («⚡ Run live», «Save», «Scan now») que a UI não exibe mais — 263 substituições em 18 locales, mapeadas a partir das fontes das views; o docs-assistant herda a correção.
Adicionado
- Bundle pré-comprimido + carregamento a frio com cache (CAR-104): o
make-bundle.mjsemitebundle.js.br(brotli q11) +.gzno momento do release; um middleware com escopo no bundle negocia br > gz comVary: Accept-Encoding,public, max-age=300, must-revalidate+ ETag/304; com guarda de atualização (um artefato companheiro nunca é servido mais antigo que o bundle de identidade), buscas diretas por artefato retornam 404, CSP byte-idêntico. Carregamento a frio: 3.1 MB → ~0.6 MB na rede (−80%); visitas repetidas dentro de 5 min transferem ≈0 bytes.
Notas
- Todas as correções vieram da frota de agentes com evidência vermelho→verde (13 + 28 + 1 + 30 + 7 casos novos em suas suítes) e passaram por rodadas de revisão (CodeQL #579/#580/#584 corrigidos no código — URLs de stub analisadas via
new URL().host, uma string morta do prompt removida). - Os números do backfill de pontuações da v1.258.0 agora estão registrados no CAR-129 (
updated: 22,reportScoreless: 159). - Deliberadamente não feito: nenhuma correção retroativa de datas para os 349 relatórios históricos (um backfill seria uma operação de ops aprovada pelo dono), nenhuma visão de clusters no mapa (o CAR-125 segue na fila atrás desta correção de geocodificação).
- Testes 5823 (+74). Nenhuma fonte do scanner tocada (registro 121 = 116 EN + 5 RU · 116 adaptadores); nenhuma chave de i18n (o CAR-108 edita apenas os valores de chaves existentes).
[1.258.0] — 2026-10-25
Seis correções da frota de agentes em um único trem: o contador de empresas do #/scan para de misturar universos, a pesquisa profunda passa a exigir fontes, erros de formulário acendem o próprio campo, estados de carregamento ganham skeleton e um h1 instantâneo, e as avaliações fazem cache do prefixo de prompt de 37k tokens.
Corrigido
- Contador «Empresas ativas» do #/scan (CAR-100): o numerador contava empresas distintas em TODAS as linhas de resultado (1554 em produção — só o hh.ru contribui com centenas) enquanto o denominador contava empresas rastreadas com suporte de API (~90) — dois universos em uma só fração. Pareamento (a): o numerador agora conta empresas entre as linhas que o próprio scan rastreado com suporte de API buscou (correspondidas por
_entry ?? company; as linhas de empregador do hh.ru/telegram saem da conta); o fallback de pré-scan migrou para o mesmo universo (ele podia exibir «104/90»). - Fabricação na pesquisa profunda (CAR-110): o prompt de deep research agora carrega um contrato rígido — toda afirmação factual termina com
[source: domain.com](não consegue nomear a fonte → não a afirme; inventar um marcador é pior do que escrever «unknown»), fatos desconhecidos são escritos comounknown, e o relatório DEVE terminar com uma seção## Data freshness. Âncoras de atualidade: a data UTC do dia + umurlopcional da empresa emPOST /api/deep(limitado, nunca buscado pelo servidor). - Erros de formulário destacam o campo (CAR-130): um POST que falha marca o primeiro campo do formulário com
aria-invalid+.is-errore move o foco para ele (WCAG 3.3.1); a marcação é limpa ao editar. A dica de erro de rede é sensível ao deployment — no loopback permanece a dica do comando de dev; uma origem implantada recebe «O servidor não está respondendo» em vez do conselhobash web-ui/bin/start.md(o banner de conexão carregava o mesmo hardcode). - Estados de carregamento (CAR-112): #/map e #/tracker renderizam o h1 instantaneamente (o alvo de foco do router só existia depois que os dados chegavam) e um helper compartilhado de skeleton (
Skeleton.rows, linhas shimmer aria-hidden dentro de uma regiãorole="status"que reutilizacommon.loading) substitui o texto nu «Carregando…» no tracker, nos resultados de scan e no shell do mapa;prefers-reduced-motioninterrompe a pulsação. - Cache do prompt de avaliação (CAR-111):
buildEvaluationPromptPartsdivide o prompt de ~37k tokens em um prefixo estável byte a byte (CV + perfil + arquivos de modo + instruções) e a cauda com a JD; o caminho Anthropic envia[prefix + cache_control: ephemeral] + [JD]— o prefixo é cobrado pela tarifa de leitura de cache (≈10× mais barato) em cada chamada depois da primeira. Prefixo ausente ou divergente faz fail open para a requisição antiga, byte-idêntica; a cascata compatível com OpenAI fica intocada (o cache lá é feito no servidor).
Notas
- As seis correções vieram da frota de agentes com evidência vermelho→verde (5 + 7 + 7 + 7 + 8 casos novos) e rodadas de revisão; os primeiros alertas CodeQL do CAR-111 (#579/#580) foram corrigidos no código — o stub de teste analisa o host da URL em vez de casar por substring, e uma string morta do prompt completo foi removida.
- O backfill de pontuações rodou em produção (endpoint da v1.256.0, com aprovação do dono):
updated: 22,missingReport: 0,reportScoreless: 159— as 159 linhas sem pontuação apontam para relatórios cujos cabeçalhos precedem o bloco de máquina ou carregam formatos de pontuação não parseáveis; recuperáveis apenas por re-avaliação ou por uma passada de parser mais ampla (anotado no CAR-129). - Deliberadamente não feito: nenhuma mudança de nulos-por-último na coluna de trajeto (o quirk pré-existente do
Infinityem descendente), nenhuma re-precificação retroativa dos registros de uso antigos, nenhum destaque no estilo.is-errorpara os formulários de filtro do scan (o CAR-130 ficou no escopo do helper compartilhado de submit da mode-page + da dica do api.js). - Testes 5749 (+36). Nenhuma fonte do scanner tocada (registro 121 = 116 EN + 5 RU · 116 adaptadores); nenhuma chave de i18n (a dica do CAR-130 reutiliza
conn.down; a região de skeleton reutilizacommon.loading).
[1.257.0] — 2026-10-25
Duas correções da frota de agentes: o assistente de ajuda do app entende devanágari e tâmil, e a página de uso mostra o que o Hermes realmente custa.
Corrigido
- Recuperação do assistente de ajuda para hi/ta (CAR-103): a classe de palavras do tokenizador de palavras-chave do docs-assistant era
[\p{L}\p{N}\u30fc]+— sem marcas combinantes. Cada matra de devanágari (ा ै ्…) e cada sinal vocálico tâmil (ே ை ்…) cortava uma palavra em fragmentos; a regra de comprimento descartava os fragmentos curtos (uma consulta em hindi casava com 0 seções) e as palavras mais longas eram decapitadas em lixo que colidia com seções não relacionadas. A classe agora mantém\p{M}; o caminho de bigramas CJK fica intocado. hi «मैं स्कैन कैसे चलाऊं?» e ta «ஸ்கேன் எப்படி இயக்குவது?» recuperam as seções certas dos bundles distribuídos. - Custo de uso do Hermes (CAR-106): o
normalizeUsage()colapsava o uso do provedor em{in, out}e descartava silenciosamente ocostreportado pelo gateway —#/usagemostrava $0.0000 em 9.5 M de tokens do Hermes (a linha dele na tabela de preços é 0/0). O formato do registro de uso ganha umcost?opcional, retrocompatível; o agregador prefere o custo reportado pelo provedor em cada registro e só recorre à estimativa da tabela de preços quando ele está ausente; valores de lixo/negativos são descartados, nunca fabricados.
Notas
- Ambas as correções vieram da frota de agentes com evidência vermelho→verde (3 + 5 casos novos; 14/14 e 10/10 verdes; vizinhos 78/78 e 61/61). Os primeiros PRs (#470/#471) carregavam uma base de worktree desatualizada que conflitava com o v1.256.0 mesclado via squash — foram substituídos por cherry-picks limpos (#472/#473).
- Deliberadamente não feito: nenhuma re-precificação retroativa das linhas históricas de
data/llm-usage.jsonl(elas não carregam campo de custo; só os registros novos se beneficiam). - Testes 5713 (+8: docs-assistant ×3, usage ×5). Nenhuma fonte do scanner tocada (registro 121 = 116 EN + 5 RU · 116 adaptadores); nenhuma chave de i18n.
[1.256.0] — 2026-10-25
Qualidade de dados do tracker: a função nunca é registrada como a empresa, um quadro de vagas nunca é registrado como o empregador, as linhas sem pontuação param de aparecer primeiro — e um endpoint de execução única preenche as pontuações faltantes a partir dos próprios relatórios.
Adicionado
- Preenchimento de pontuações (CAR-129):
POST /api/tracker/backfill-scorespreenche a célula Score das linhas cujo relatório vinculado carrega uma pontuação parseável (181 linhas avaliadas tinham relatório, mas nenhuma pontuação). Linhas já pontuadas, sentinelas explícitas (N/A), linhas sem relatório e relatórios sem pontuação nunca são tocados; só a célula Score é reescrita, sob o file lock; o formato da pontuação é validado no ponto de escrita e normalizado para a convençãoX.X/5do tracker; a execução é idempotente e retorna{ok, updated, missingReport, reportScoreless}.
Corregido
- A função nunca é a empresa (CAR-128): o
guessCompanyRoletratava o lado ESQUERDO de uma linha de cabeçalho com travessão como a empresa, mas os quadros escrevem as duas ordens — «Senior Frontend Engineer - Grafana Labs» registrava a função COMO a empresa (13 linhas: Grafana, CircleCI…). Uma heurística de palavras-chave de função com fronteiras de palavra agora escolhe o lado da função, e um tipo de vínculo nunca se torna o empregador («Senior Engineer - Remote (EU)» não registra nada em vez de «Remote (EU)»). - Um quadro de vagas nunca é o empregador (CAR-127): o fallback de slug de domínio registrava as linhas do hh.ru como «hh» (120 linhas). Os slugs
hh/habrentram na lista de não-empregadores; a inferência de empregador em meio à frase («в компании X», «X ищет») agora roda também para os hosts de quadros de vagas (hh.ru/kz/uz/by, habr.com) — onde o texto da página nomeia o empregador real. A causa raiz apareceu no caminho: o\b/\wASCII desses padrões de inferência nunca casou com cirílico — silenciosamente mortos desde a v1.248.4; lookbehinds Unicode e classes\p{L}os substituem. - Linhas sem pontuação ordenam por último (CAR-129): a ordenação por pontuação do tracker usava uma sentinela
-1, então com a ordenação ascendente padrão toda linha sem pontuação aparecia antes de todas as pontuadas. Os nulos agora ordenam por último nas duas direções (o FILTRO de pontuação mantém o seu-1— «sem pontuação falha num filtro ≥4» é a semântica correta ali).
Notas
- As linhas históricas NÃO são migradas por esta versão: as correções do parser valem para novas avaliações; as pontuações são recuperáveis pelo endpoint de preenchimento, enquanto as 120 células de empregador «hh» precisam de re-avaliação, não de reescrita.
- Uma rodada de revisão opus-5-5 é incorporada: o padrão não ancorado «X ищет» foi descartado antes do lançamento (qualquer sequência capitalizada antes do verbo teria sido registrada como empregador — o invariante de não-fabricação), âncoras «В…» em início de frase foram adicionadas, e o escritor do backfill re-checa a célula alvo (linhas
#duplicadas existem após edições manuais), preserva a contagem de colunas de uma linha curta malformada à mão e para na primeira linha fora da tabela. O ponto dentro de um nome pontuado («Сбер. IT») é indistinguível de um ponto de frase para a âncora «в компании» — o prefixo conservador («Сбер») é registrado; o padrão ancorado no verbo captura a forma completa. - Deliberadamente não feito: nenhuma extração do comparador de
tracker.jspara uma biblioteca testável unitariamente (o portão estático-de-fonte permanece; anotado no CAR-129 como follow-up), nenhuma mudança de nulos-por-último na coluna de trajeto (o quirk pré-existente doInfinityem descendente), nenhuma migração de dados para as linhas «hh». - Testes 5705 (+10: 5 de identidade em
auto-pipeline-jd-gate, 2 CAR-128, o portão de ordenação do CAR-129, 4 de backfill incluindo o pin de caminho hostil — menos os casos substituídos da v1.248.x). Nenhuma fonte do scanner tocada (registro 121 = 116 EN + 5 RU · 116 adaptadores); nenhuma chave de i18n.
[1.255.2] — 2026-10-24
Três correções visíveis para o usuário vindas da regressão ao vivo e de um relato de crash em produção: o crash de renderização do #/scan, a checagem de idioma vietnamita às cegas e a perda recorrente do bloco de resumo no zh-TW.
Corregido
- Crash do #/scan (CAR-99): a regeneração dos count gates desde a v1.253.0 escreveu o literal
FALLBACK_SOURCEScom vírgula dupla no final de cada entrada — 120 buracos de elisão no array.new Set(FALLBACK_SOURCES.map((s) => s.value))na view de scan passou então a conterundefined, e oid.lengthdo classificador de empresas lançavaTypeError: Cannot read properties of undefined (reading 'length')em cada renderização de página (capturado pelo logbuf em produção). Os buracos foram removidos e um novo portão (4 specs, verificado em vermelho) executa o arquivo e falha diante de qualquer buraco, entrada inutilizável ouundefinedno Set de ids de adaptadores — o portão de drift só-texto não podia ver essa classe. - Checagem de idioma vi às cegas (CAR-97): o vietnamita é escrita em alfabeto latino e não tinha entrada na tabela de stop words da QA ao vivo, então as «stop words de vi» contavam acertos em inglês e uma resposta em vietnamita era lida como
report not in vi(regressão ao vivo: vi 2, en 2). O vietnamita agora tem sua própria tabela de dez palavras funcionais — um relatório puramente vietnamita passa, e um em inglês continua falhando. - zh-TW perdia o bloco SCORE_SUMMARY (CAR-98): o lembrete final de idioma só dizia que o formato de máquina não deve ser traduzido, nunca que o bloco de resumo precisa existir — um relatório curto em zh-TW (5,983 caracteres) carregava os blocos A–G mas omitia o bloco por inteiro (uma recorrência da classe v1.239.2). A diretiva de abertura e o lembrete final agora afirmam que o bloco é obrigatório e que sem ele o relatório é inválido.
Notas
- Esta versão deliberadamente não muda nenhuma fonte do scanner, a contagem do registro (121 = 116 EN + 5 RU · 116 adaptadores) nem a fiação dos provedores — é só de correções, então os count gates ficam intocados.
- Testes 5695 (+9:
car99-fallback-holes×4,car97-vi-lang-check×4, o invariante de prompt do CAR-98 ×1). Navegador 143/143. A re-checagem ao vivo de vi/zh-TW acompanha a regressão pós-deploy.
[1.255.1] — 2026-10-24
Duas rodadas de correção vindas de revisões: a revisão Opus da localização vietnamita (9 achados) e a segunda passagem sobre as correções CAR-91/92 (5 must-fix) — ambas fechadas com testes vermelho→verde.
Corregido
- Rodada de revisão da localização vi (desdobramento do CAR-88): o glifo Hangul (
신) que vazou paraproject.subtitle/project.roleHintestá corrigido (độ khớp tín hiệu), com um portão que falha diante de qualquer glifo CJK/Kana num valor de vi que o dicionário EN não carrega; as seis URLs de markdown com espaços em docs/help/vi.md (what-is career-ops,apply for a job,set up playwrighte mais três) recebem hífens para virar os slugs reais dos guias, com um portão de sem-espaços-em-URLs. - Fronteiras de cabeçalhos de avaliação (CAR-92 r2 H1):
&,.,/,'agora são caracteres de palavra na fronteira esquerda da letra de bloco —## Q&A,## Plan B,## Ph.D. requirement,## E-commercenão são mais registrados como blocos A/B/D/E; o terminador de fim de linha puro é aceito só depois de um token de palavra-de-bloco (Block/блок/블록/…); o-ASCII saiu das classes de terminador soletrado para que os cabeçalhosE-commerce/ई-मेलsobrevivam. - Relatórios numerados em ucraniano/russo (CAR-92 r2 H2): o detector de sequência А Б В Г Д Є Ж agora é um auxiliar compartilhado; quando ele encontra 3+ letras de sequência num nível de cabeçalho, esse nível se torna o nível de referência do cortador — subseções
### A.com letra não truncam mais o relatório no bloco Б. - Ciclo de vida das linhas carregadas (CAR-92 r2 M1): linhas que uma fonte falhada carrega para o próximo scan são carimbadas com
carriedSince, descartadas após 30 dias ou 5 carregamentos consecutivos, e acrescentadas depois das linhas frescas em vez de re-acumular silenciosamente para sempre. - Denominador do synthesis do Gemini + legitimidade (CAR-92 r2 M2) e o caminho de body-score do subprocesso (M3): lidos do arquivo de achados, corrigidos com testes vermelhos.
- Portão de drift do bundle de cold-load atualizado para o dicionário vi (90 script tags / 87 empacotáveis) e sua binding de teste não usada removida (CodeQL 572).
Notas
- A frase da contagem de adaptadores no banner “Latest” do README.vi que a revisão apontou vive no banner Anterior e já espelha o README EN byte a byte — deixada intocada para manter a paridade EN↔vi (documentado no corpo do commit).
- Testes 5686 (+26:
eval-validate-opus-r2,scanner-carryover-r2, asserções do portão vi). Registro inalterado em 121 fontes (116 EN + 5 RU) · 116 adaptadores.
[1.255.0] — 2026-10-24
O vietnamita (Tiếng Việt) entra como o 19.º idioma da interface — um dicionário de 1525 chaves com paridade total com o EN, detecção de vi/vi-VN, o pacote de ajuda completo, espelhos de README e CHANGELOG, integração na landing do cvstart.org e a 🇻🇳 no seletor de idioma.
Adicionado
- Vietnamita (
vi) — 1525/1525 chaves com paridade total comen;detect()aceitavievi-VN; o vietnamita é LTR (nunca adicionado aRTL_LANGS). «Pipeline» continua «Pipeline» — empréstimo técnico padrão, na lista de permissões. - docs/help/vi.md completo (33 H2 / 125 H3), além dos espelhos README.vi.md e CHANGELOG.vi.md e as strings de andaime em vietnamita no
prompts.mjs(LOCALE_NAMES+SCAFFOLD_STRINGS) para que a saída de LLM em vietnamita funcione de fábrica. - Landing do cvstart.org em vietnamita —
site/src/i18n/vi.json, a entrada de locale no sitemap e uma capturadashboard-vi.png; o seletor de idioma ganha a 🇻🇳 (19 posições). - Portões de enumeração 18 → 19 — LANGS, sondas de detect, auditoria i18n, paridade do changelog, bloco de traduções do README, varredura de locales — mais o
tests/i18n-vi-locale.test.mjsvermelho-primeiro (139 linhas).
Notas
- A landing do cvstart.org ganha o vi — um desvio deliberado do precedente do ta (aquela versão manteve a landing em 17 de propósito); documentado na especificação da versão.
- vi é de escrita latina, então o portão no-latin-leaks não se aplica (ele guarda os idiomas não latinos); vocabulário técnico latino é a norma.
- Piso de testes: 5634 → 5642 (1 ignorada = o teste opcional de captura de layout do navegador, inalterado).
[1.254.0] — 2026-10-24
Uma versão de endurecimento da rodada de revisão com o modelo máximo: o snapshot do scanner nunca mais perde linhas, onze violações invariantes da camada LLM estão corrigidas, vinte e três must-fix do SPA aterrissam, e o ATS Paylocity se junta ao scanner — o registro agora entrega 121 fontes (116 EN + 5 RU) com 116 adaptadores.
Adicionado
- Paylocity ATS (pai #5687): quadros por tenant
recruiting.paylocity.com, quadro morto 302 → JobNotFound mapeado para 404 para que a quarentena retire a entrada, tetomax_jobscom bandeira de truncamento. Registro: 121 fontes = 116 EN + 5 RU · 116 adaptadores; os gates de contagem regenerados.
Corregido
- Segurança do snapshot do scanner (R-12): uma varredura que não tenta nada agora CONSERVA o snapshot (
nothing scanned); um replace completo carrega as linhas antigas das fontes falhadas — carimbadas por entrada — re-passadas pelos filtros ATUAIS, pousando só emfiltered. - Onze invariantes da camada LLM: diretiva de idioma que abre E fecha os prompts deep/mode; subprocesso Gemini com
--lang, 502 em saída não-zero, stderr sem vazar ao cliente, 300 s e usage registrado; fallback manual com URL; truncamento visível em/api/mode; o spend tier não é mais alterado pelo cliente; a desconexão do cliente aborta a chamada ao provedor; o cortador de cabeçalhos repetidos não destrói mais relatórios válidos; extratores score/legitimacy alinhados; falsos-aceites uk e árabe apertados. - Uma rodada de revisão Opus 5-5 SOBRE as correções (8 imperativos): registro multi-letra do cortador, terminadores mais amplos, abort do subprocesso Gemini, atribuição carimbada do arrasto, re-filtragem de linhas arrastadas, nível de referência por letras distintas.
- Vinte e três must-fix do SPA nas visões de sourcing e assistência (pager de página única, teclado de pipeline, restauração de filtros, resets de select, reversão de padrão em config, vazamentos de listeners, fechamento SSE no terminal, teardown do runner, fetch pelado, cargas falhadas que pareciam vazias, colisão global, preservação de foco; deep-link morto do help, vazamentos do help, re-arme do blank-overwrite no two-pager, single-flight de execuções pagas batch/deep/mode, fins silenciosos de stream, spinners eternos em erros, linhas fantasmas de filtros falhados, duplicados do docs-fab + idioma).
Notas
- A rodada inteira foi revisada pelo Opus 5-5 em rigor máximo — os portos pré-merge (21 achados, 13 corrigidos) e os próprios fixes post-hoc (8 imperativos, todos aqui com testes vermelho→verde).
- Piso de testes: 5262 → 5634 (372 novas specs em fontes, scanners, camada LLM e SPA).
[1.253.1] — 2026-10-24
Dois achados HIGH de segurança da revisão com o modelo máximo estão corrigidos: URLs literais IPv6 não mais contornam a guarda SSRF do scanner, e o regex de escape do markdown do CV não mais retrocede quadraticamente.
Corregido
- Literais IPv6 burlavam a guarda SSRF (
http-json.mjs): um literal IPv6 entre colchetes faziadns.lookuplançar e a guarda falhar aberta. Agora os colchetes são removidos e o literal é classificado viaisIP— sem DNS, sem fail-open. - ReDoS no escape do markdown CV (
security.mjs): o padrão retrocedia quadraticamente —<+ ~100k espaços custavam ~16 s; agora ~1 ms com uma classe plana limitada. Tudo que era escapado antes continua sendo.
Notas
- Ambos fixos levam testes vermelho→verde (3 casos IPv6 novos + ReDoS com cota de tempo; 5511 testes, +7).
- Os arquivos de fonte do scanner não são afetados — a guarda vive no transporte compartilhado.
career-ops-ui v1.267.1 · page 1/9 · mirror of the project changelog for cvstart.org