Changelog 3.1.0
O que mudou no SpiderHead, release por release. Cada entrada informa o tipo da mudança e se ela funciona hoje.
3.1.0
Primeira release com tag após a renomeação de SEOHEAD Tools11 de outubro de 2026455 entradas11 de outubro de 2026
5 adicionado54 alterado2 corrigidoAlteradoFuncionaReconstrói Agenda e Rastreamento das configurações do projeto com componentes nativos de#1323
canvas compartilhados, fontes Roboto offline e Material Symbols, e layout de coluna única em 800 px.
#1323 (issue no GitHub)AlteradoFuncionaUsa inglês em toda a interface do aplicativo, mantém o comando de agendamento existente e#1323
os contratos de documento, e exibe apenas dados de agendamento respaldados pelo núcleo.
#1323 (issue no GitHub)AlteradoFuncionaPreserva identidades e aliases de workspace enquanto as Configurações do projeto estão#1323
abertas; impede salvamentos duplicados enquanto o núcleo responde.
#1323 (issue no GitHub)AlteradoFuncionaAs configurações do projeto no desktop ganham uma aba Agenda (dias da semana, dias do#1322
mês, janela de execução, fuso horário, concorrentes) e uma aba Rastreamento (modo de rastreamento, predefinição ou string personalizada de User-Agent, pausa entre requisições, orçamento de URLs, SpiderHeadBot ou um user agent personalizado); ambas leem e gravam o projeto pelo núcleo, e a visão geral do projeto mostra a próxima e a última execução agendada. Um modo --tray executa os scans vencidos do núcleo e mantém o Mac acordado apenas enquanto um scan roda.
#1322 (issue no GitHub)AlteradoFuncionaScans agendados de projeto (#1322, núcleo):
schedule.jsonno diretório do projeto#1322guarda…
Scans agendados de projeto (#1322, núcleo): o
#1322 (issue no GitHub)schedule.jsonno diretório do projeto guarda a programação (dias da semana e/ou dias do mês, janela de horário no fuso horário do site, ativar ou desativar, concorrentes, modo de rastreamentospider/sitemap/list, orçamentos de URLs e de requisições por execução, intervalo de cortesia entre requisições e modo de fatias, que retoma o rastreamento parcial anterior). Ele é editado porschedule-set/seo_schedule_setcomexpected_revision, e oschedule-showmostra a última execução e a próxima janela devida. Oschedule-run-dueé um ponto de entrada sem interface que executa só os scans vencidos, recusa sobreposição com um lease e registra cada decisão no diário do projeto.schedule-installeschedule-uninstallgravam ou removem um plist do launchd, uma linha de cron ou um comando do Agendador de Tarefas somente quando são chamados explicitamente.AlteradoFuncionaUser agents de rastreamento (#1322): predefinições (
spiderhead,googlebot,#1322
#1322 (issue no GitHub)googlebot-desktop,googlebot-smartphone,bingbot,yandexbot,yandexmobilebot,baiduspider,duckduckbot,applebot,gptbot,claudebot,perplexitybot, além de navegadores para desktop e mobile) ou uma string personalizada. O padrão agora éSpiderHeadBot/<version> (+https://github.com/PavloSEO/spiderhead), e a correspondência do grupo do robots.txt usa a mesma identidade. Sites que correspondiam ao grupo antigoSEOHEAD-Toolsno robots.txt devem citarSpiderHeadBotnas suas regras.AlteradoFuncionaUm rastreamento de projeto salvo agora marca os itens automáticos do checklist que ele#1314
mediu.
Cada item ativo do checklist recebe um de três resultados:
#1314 (issue no GitHub)succeeded, quando a auditoria salva executou a verificação, com o scan como evidência;unavailable, quando o rastreamento pulou ou desativou a verificação, mantendo o motivo informado por ele; ouunmeasured, quando a auditoria não menciona a verificação. Um item não medido mantém o registro anterior e aparece pelo nome emchecklist_evidence, então nunca conta como 0. Um rastreamento que falha ou é interrompido marca suas verificações automáticas comofailed, com o motivo da falha. O mesmo caminho de registro agora atende o fluxoprepare, que antes tinha uma cópia própria do loop. Um projeto com checklist não inicializado é ignorado, com o motivo informado.AlteradoFuncionaWorkspaces de concorrentes mantêm a URL como foi digitada: o rastreamento começa pela URL#1314
www…Workspaces de concorrentes mantêm a URL como foi digitada: o rastreamento de um concorrente começa pela URL
#1314 (issue no GitHub)www, em vez do host puro, e o rastreamento de uma URL de concorrente não marca mais os itens do checklist do dono; o resultado é registrado somente no workspace do próprio concorrente. Abrir um projeto com workspace de concorrente danificado informa que esse concorrente está indisponível, em vez de falhar.AlteradoFuncionaCandidatos a concorrente podem ser registrados, listados e removidos pela CLI#1314
(
#1314 (issue no GitHub)project-competitors-add,project-competitors-list,project-competitors-remove) e pelas ferramentas MCPseo_project_competitors_*correspondentes. Cada candidato mantém a URL como foi digitada, incluindo um hostwww, e hosts com e sem www contam como o mesmo site nas verificações de duplicidade. Um concorrente com hostwwwnão quebra mais a preparação nem faz oproject-observefalhar.AlteradoFunciona
--max-urlsagora é o orçamento de páginas do rastreamento: um orçamento explícito#1314preenche os de requisições…
#1314 (issue no GitHub)--max-urlsagora é o orçamento de páginas do rastreamento: um orçamento explícito preenche os orçamentos de requisições e de tempo que não foram definidos (3 requisições e 2 segundos por página), então rastreamentos de 50–300 páginas são aceitos semapprove_large_crawl; orçamentos acima dos limites do projeto continuam sendo recusados.AlteradoFuncionaUma parada deliberada por orçamento de URLs é salva como captura concluída, com#1314
#1314 (issue no GitHub)finish_reasonstopped_by_budgete um horáriofinished_at, em vez deinterruptedsem horário de término. As URLs que ficaram na fila permanecem para uma retomada.AlteradoFuncionaURLs de concorrentes mantêm o host como foi digitado (por exemplo,
www.continua), em#1314vez de serem armazenadas sem ele.
#1314 (issue no GitHub)AlteradoFuncionaO Desktop adiciona sites concorrentes pela área de transferência ou um a um pelo núcleo,#1314
define um limite de URLs por site e inicia os scans deles em paralelo; um concorrente só aparece como escaneado depois de um scan retido e concluído.
#1314 (issue no GitHub)AlteradoFuncionaScans nativos medem HSTS, conteúdo misto e dados estruturados a partir das evidências#1314
armazenadas…
Scans nativos medem HSTS, conteúdo misto e dados estruturados a partir das próprias evidências armazenadas, então uma exportação do SF ausente ou desatualizada não os aponta mais como ausentes. O
#1314 (issue no GitHub)duplicate-checkmarca como não medida uma execução com zero pares comparados. Problemas de template em todo o site (mesmo bloco de layout no cabeçalho, baixa proporção de texto) viram um único problema com a contagem de páginas (#1314).AlteradoFuncionaAceitar uma meta do dono adiciona apenas a tarefa de checklist dessa meta.#1314
Isso não reconcilia mais todo o catálogo interno com
#1314 (issue no GitHub)coverage.json; as linhas internas são adicionadas sob demanda, quando uma delas é tocada.AlteradoFuncionaUm checklist ocupado identifica o detentor ativo (por exemplo, um rastreamento nativo em#1314
execução e o seu pid), em vez de chamar o lock de resíduo. O lock registra o pid de quem escreve; um lock sem detentor ativo continua sendo reportado como resíduo.
#1314 (issue no GitHub)AlteradoFuncionaUma execução de workflow bloqueada por uma etapa com falha, indisponível, ignorada ou#1314
interrompida continua retomável, e uma etapa pendente posterior pode receber checkpoint mesmo após uma etapa sem sucesso. As etapas ainda precisam receber checkpoint na ordem registrada, e uma execução interrompida continua recusando novas etapas.
#1314 (issue no GitHub)AlteradoFuncionaUma revisão registrada por agente deixa de tornar um item manual ou entregável completo#1314
pelo dono.
O item continua aguardando a aprovação do dono ou de um revisor que não seja agente.
#1314 (issue no GitHub)AlteradoFuncionaReferências da caixa de entrada aceitam ids de metas (
inbox:<uuid>), para que uma nota#1314cite a meta a que se refere…
Referências da caixa de entrada aceitam ids de metas (
#1314 (issue no GitHub)inbox:<uuid>), para que uma nota possa citar a meta a que se refere.AlteradoFuncionaItens do checklist nunca tentados e manuais passam a mostrar o estado
not_run, em vez#1314de
#1314 (issue no GitHub)review; apenas uma tentativa aguardando decisão permanece emreview.AlteradoFuncionaO modelo de leitura de Issues (evidências de problemas do
observe) informa contagens#1314por verificação (
#1314 (issue no GitHub)by_check) e umnext_offsetapós os primeiros 20 problemas;findings_pagepagina pelo restante.AlteradoFuncionaVerificações nativas de rastreamento (#1314): o tamanho de imagem (
IMG_OVER_KB) agora é#1314medido a partir das próprias requisições de imagem do rastreamento, e o status do sitemap (
#1314 (issue no GitHub)SITEMAP_URL_4XX_5XX,SITEMAP_URL_3XX,SITEMAP_URL_NON_INDEXABLE) a partir da busca feita pelo próprio rastreamento em cada URL listada no sitemap. Uma URL listada que o rastreamento nunca requisitou é contada como não medida, nunca como limpa.IMG_MISSING_ALT,IMG_MISSING_DIMENSIONSeHREFLANG_ERRORinformam, em um scan nativo, que o rastreamento não os mede da forma como a exportação do SF define, em vez de apontar para um filtro do SF. Hreflang ausente e evidência de conteúdo misto em um scan nativo são reportados como não medidos pelo rastreamento nativo, e não como exportação ausente.AlteradoFuncionaDiário do projeto (#1314): cada evento do projeto agora também é gravado como um item em#1314
#1314 (issue no GitHub)log.md, e o núcleo registra entradas automáticas para rastreamentos concluídos (scans), relatórios de projeto gerados e tentativas de checklist (agent). As entradas vão paraevents.jsonle são lidas porproject-event-page; os ganchos automáticos nunca fazem falhar o rastreamento, o relatório ou a etapa de checklist que descrevem.project-event-appendeseo_project_event_appendmantêm sua interface e ganham a linha emlog.md.AlteradoFuncionaO rastreamento nativo agora armazena os cabeçalhos de segurança que as verificações leem#1314
(
#1314 (issue no GitHub)Strict-Transport-Security,Content-Security-Policy,X-Frame-Options,X-Content-Type-Options,Referrer-Policy,Permissions-Policy). Antes, eles eram descartados na captura, então um site que enviava HSTS era apontado como sem HSTS. Os cabeçalhos Set-Cookie guardam apenas suas flags (secure,httponly,samesite=), nunca o nome ou o valor do cookie. Um cabeçalho de segurança enviado mais de uma vez na mesma página é reportado comoDUPLICATE_SECURITY_HEADER.AlteradoFunciona
workflow-startprecisa só de uma meta aceita pelo dono:--goal-id(ou#1314context.goal_id)…
#1314 (issue no GitHub)workflow-startprecisa apenas de uma meta aceita pelo dono:--goal-id(oucontext.goal_id) basta. O prompt registrado usa por padrãoskill:workflow/full-audit-v1, e a tarefa de checklist usa por padrão a que aceitou a meta criada (custom:goal-<entry>). As recusas informam o comando do dono que corrige o vínculo que falta. As opções estão documentadas emseohead workflow-start --help.AlteradoFuncionaPopulações de checklist aceitam objetos parciais: apenas
kindesourcesão#1314obrigatórios, e as demais chaves ficam sem valor por padrão. Uma população recusada informa as chaves ausentes ou desconhecidas.
#1314 (issue no GitHub)AlteradoFuncionaRastreamentos nativos de projeto usam o
/sitemap.xmlda origem como alternativa quando#1314o robots.txt não declara nenhum sitemap. Quando essa alternativa não existe, ela é registrada como incompleta, mas não interrompe o rastreamento.
#1314 (issue no GitHub)AlteradoFuncionaLogs de servidor agora guardam totais exatos de IPs de bots em disco, em vez de uma#1311
amostra limitada, com registros por IP limitados, visitas, última visita e filtros por sub-rede. A verificação explícita de DNS checa separadamente cada IP selecionado, registra evidências de PTR e de resolução direta, suporta IPv6 e preserva os resultados de indisponível ou prazo esgotado como não verificados. Caches locais expiram após uma hora; leituras nunca disparam consultas DNS.
#1311 (issue no GitHub)AdicionadoFuncionaAdicionados: importação local de logs do projeto, resumo paginado, evidências de bots e#1311
junção com scans nativos…
Adicionados: importação local de logs do projeto, resumo paginado, evidências de bots e comandos de junção com scans nativos, pelos handlers compartilhados da CLI e do MCP. Os artefatos de log separados mantêm partições por data e a cobertura e a proveniência das fontes, sem alterar os esquemas congelados dos scans. Evidência ausente ou incompleta retém conclusões de ausência. As telas de logs do Desktop continuam como um acompanhamento de apresentação separado.
#1311 (issue no GitHub)AlteradoFuncionaControla as chamadas de produção ao Google DataForSEO antes da criação do cliente, expõe#1310
cotações offline a partir dos preços de provedor fornecidos, considera a profundidade de SERP e as cobranças por operador de busca, e aplica tetos conhecidos em USD por chamada antes do transporte. Expande operações limitadas de índice de backlinks e registra no diário os custos ausentes ou formatos de resposta malformados como recibos incertos. Os limites de moeda por projeto e por mês continuam pendentes de uma decisão do dono.
#1310 (issue no GitHub)AlteradoFuncionaMescla evidências explícitas de origem e importação de backlinks em snapshots locais#1310
privados de histórico, com observações completas de tokens de rel, âncoras, domínios de referência, filtros e sinais transparentes de revisão de spam. Adiciona rotas CLI/MCP de perfil e de exportação revisada de disavow, sem envios automáticos.
#1310 (issue no GitHub)AdicionadoFuncionaAdiciona avisos de revisão de tokens rel mistos e de divulgação de patrocínio em links de#1310
saída, a partir de evidências nativas retidas, preservando o contexto indisponível, contagens nulas para populações HTML totalmente não analisadas e as classes sponsored, ugc e nofollow nos relatórios e nas verificações de doadores, sem alterar o esquema congelado dos scans retidos.
#1310 (issue no GitHub)AlteradoFuncionaVerificações nativas de DOM e de duplicidade agora leem o documento retido selecionado de#1307
cada página pela URL exata, com linhagem verificada de resposta e corpo. Desativação de retenção, corpos ausentes, inválidos ou acima do orçamento continuam como omissões explícitas; problemas parciais carregam cobertura. Hashes exatos da área de conteúdo e problemas SimHash/LSH limitados persistem na auditoria nativa sem exigir um diretório HTML do SF. As faixas LSH adaptadas ao limiar preservam o recall de pares qualificados e reduzem os buckets de candidatos amplos; o esgotamento do orçamento da análise de quase-duplicatas não descarta os problemas de hash exato.
#1307 (issue no GitHub)AlteradoFuncionaAuditorias do SF executam opcionalmente similaridade semântica e revisão de title/H1#1307
versus corpo retido, com um adaptador local fornecido explicitamente ou embeddings declarados. Nenhum modelo ou provedor é escolhido automaticamente. Identidade do adaptador, hashes de origem, scores, limites e omissões acompanham os candidatos à revisão; similaridade semântica não afirma conteúdo duplicado, relevância para a consulta nem canibalização. As duas linhas de cobertura semântica do SF continuam como lacunas até que um adaptador real seja escolhido e validado. A autorização de provedor externo exige o booleano literal
#1307 (issue no GitHub)true; valores que apenas parecem verdadeiros, como strings ou inteiros, nunca autorizam uma chamada de embedding.AlteradoFuncionaAuditorias nativas retidas agora agrupam links internos quebrados por destino observado,#1306
com evidências de origem e âncora; registram cadeias e loops de redirecionamento com o status de cada salto; diferenciam busca interna baseada em caminho e âncoras vazias; e expõem resultados capturados de links externos sem resposta. Problemas de consistência de sitemap e robots usam pertencimento e evidências de resposta retidos, sem novas buscas ao vivo; evidências ausentes ou parciais continuam explícitas.
#1306 (issue no GitHub)AdicionadoFuncionaAdicionado um grafo de links limitado de scans salvos, com filtros de#1306
posição/seção/vizinhança local…
Adicionado um grafo de links limitado de scans salvos, com filtros de posição, seção e vizinhança local, agregação por seção e mudanças de arestas entre scans. A reanálise offline preenche as posições com lotes derivados retomáveis e informa evidências não classificadas na inspeção de links e no status do scan, preservando o esquema congelado scan.v1.
#1306 (issue no GitHub)AdicionadoFuncionaAdicionada geração local de sitemap XML a partir de páginas 200 canônicas e indexáveis#1306
retidas, com lastmod observado, exclusões, divisão conforme o limite do protocolo, índice de sitemap e sitemap de imagens opcional. CLI e MCP usam as mesmas implementações; a publicação da saída exige um diretório local novo e nunca faz deploy de arquivos.
#1306 (issue no GitHub)AlteradoFuncionaPreserva alvos de descoberta ausentes no momento da captura quando um processamento#1306
posterior de sitemap ou seeds…
Preserva alvos de descoberta ausentes no momento da captura quando um processamento posterior de sitemap ou de seeds adiciona a URL ao catálogo retido. Evidências explicadas de não resolvido ou excluído permanecem imutáveis, enquanto alvos conhecidos declarados e divergências de identidade não nulas continuam inválidos.
#1306 (issue no GitHub)AlteradoFuncionaA geração de sitemap de imagens exclui respostas de recursos conhecidas diferentes de#1306
200, mesmo quando o recurso não foi armazenado como página rastreada, e marca respostas de imagem não medidas como cobertura parcial.
#1306 (issue no GitHub)AlteradoFuncionaRetém atributos brutos de canonical e paginação como contexto versionado do documento,#1305
sem alterar o SQL congelado do scan. Links canonical com atributos hreflang, lang, media ou type não suportados, anotações malformadas e declarações entre hosts ou protocolos diferentes agora geram problemas com evidência vinculada; palavras-chave de relação bem formadas e desconhecidas continuam não classificadas.
#1305 (issue no GitHub)AlteradoFuncionaEstende sondagens limitadas de alvos no mesmo host para a paginação e retém observações#1305
medidas de noindex/canonical…
Estende sondagens limitadas de alvos no mesmo host para a paginação e retém observações medidas de noindex e canonical. Cadeias canonical nativas e problemas de noindex em canonical/hreflang podem usar as sondagens; sondagens antigas, só de status, continuam legíveis e não medidas para diretivas HTML.
#1305 (issue no GitHub)AlteradoFuncionaJulga cadeias de paginação nativas opacas quanto a contradições explícitas e recíprocas#1305
de next/prev, mantendo as regras numeradas e de passo e os estados nomeados como não julgados. Seleciona as URLs dos problemas salvos, inclusive dos membros agrupados, por meio de scan-url-query, usando tabelas temporárias do SQLite e evidências audit.v2 em streaming.
#1305 (issue no GitHub)CorrigidoFuncionaMantém tokens de relação Unicode desconhecidos e com pontuação como não classificados,#1305
normaliza autoridades canonical equivalentes com IDN ou porta padrão e preserva os caminhos-alvo exatos da paginação nativa. Tokens de página mistos ilegíveis continuam não julgados; o defeito de paginação da loja é reconhecido mesmo quando a página um não tem número na URL.
#1305 (issue no GitHub)AlteradoFuncionaRenderiza as anotações next/prev declaradas no fixture da loja, para que sua verdade de#1305
referência D41 de paginação seja realmente servida e possa ser validada pela captura nativa.
#1305 (issue no GitHub)AlteradoFuncionaRetém evidências estáticas de AMP e de acessibilidade vinculadas ao documento nas linhas#1304
de contexto de scan existentes, preservando o esquema SQL congelado
#1304 (issue no GitHub)scan.v1. Problemas estruturais de AMP inspecionam a declaração doctype original, head e body, charset UTF-8, viewport, script de runtime e declarações de boilerplate; alvos AMP pareados sem marcador de raiz AMP são identificados à parte. As regras completas do validador AMP continuam indisponíveis até que haja uma decisão de licença.AlteradoFuncionaInicia problemas de acessibilidade sobre idioma do documento, rótulos de formulário,#1304
textos alternativos de imagem, saltos de título e o landmark main. Os problemas preservam exemplos limitados e contagens completas de ocorrências. Contraste calculado e regras de axe-core renderizadas continuam não medidas.
#1304 (issue no GitHub)AlteradoFuncionaValida Microdata do Schema.org e sujeitos e propriedades comuns de RDFa com o vocabulário#1304
incluído e as regras existentes de resultados avançados. Erros, avisos e propriedades obrigatórias ausentes retidos por URL viram problemas nativos. Construções RDFa não suportadas são evidência parcial explícita, não um resultado de validação limpo.
#1304 (issue no GitHub)AlteradoFuncionaServe árvores JSON-LD analisadas junto com erros por bloco de origem, posição e sintaxe#1304
em
#1304 (issue no GitHub)scan-structured-blocks; limita árvores de propriedades muito largas e expõe esse limite. Lê o documento mais recente de uma URL e de uma representação solicitadas, sem alterar o seu scan.AlteradoFuncionaPreserva evidência estruturada parcial ou indisponível sem ocultar erros irmãos#1304
confirmados.
Resolve identidades JSON-LD suportadas contra a mesma base de documento da marcação HTML, preservando o JSON de origem; rejeita blocos JSON escalares ou vazios como grafos válidos e compartilha a seleção normalizada de tags JSON-LD ao vivo entre o parser e as projeções servidas.
#1304 (issue no GitHub)AlteradoFuncionaAuditorias nativas agora expõem marcação no head que bloqueia a renderização, a partir de#1303
HTML retido completo, sem…
Auditorias nativas agora expõem marcação no head que bloqueia a renderização, a partir do HTML retido completo, sem alterar o esquema congelado scan.v1. Corpos ausentes, incompletos ou limitados pelo orçamento continuam indisponíveis. A detecção existente de recursos do head e a entrada de extração personalizada do SF são reaproveitadas.
#1303 (issue no GitHub)AdicionadoFuncionaAdiciona orçamentos configuráveis de navegação observada e de bytes por recurso#1303
individual…
Adiciona orçamentos configuráveis de navegação observada nativa e de bytes por recurso individual, sinais de entrega de cache e fontes, heurísticas de minificação e de scripts legados, e duplicatas exatas de script na mesma página, a partir das evidências retidas do scan.v2. Dados não buscados e cargas de runtime incompletas continuam explícitos; declarações responsivas não são somadas como peso de runtime. Limites inferiores apenas com HTML, contagens escalares de cobertura, amostras de fontes e resumos de origem continuam explícitos e limitados.
#1303 (issue no GitHub)AlteradoFuncionaColeta cobertura precisa limitada de JS/CSS do Chromium em renders solicitados, retém#1303
resumos de uso em UTF-16 e problemas de dimensionamento de imagem renderizada, e os lê após reabrir ou na reanálise offline. Motores não suportados e medições ausentes não viram resultados limpos.
#1303 (issue no GitHub)AlteradoFuncionaAceita JSON do Lighthouse por URL, limitado e correspondente, para descoberta de LCP,#1303
árvores de dependência, responsáveis por layout shift, entrega de imagens, reflow forçado e problemas de execução de script, com proveniência de captura e hashes das entradas. Nenhum processo do Lighthouse, provedor pago ou inferência de CWV de campo é adicionado. Atualiza o registro, a cobertura do SF e a documentação de referência gerada.
#1303 (issue no GitHub)CorrigidoFuncionaMantém os limiares de recursos adicionais fora do cabeçalho congelado do scan nativo e#1303
armazena seus valores exatos em um contexto de execução validado e versionado. A retomada compara esses valores separadamente, e a reanálise offline os restaura a partir das evidências retidas; leitores leves mais antigos ainda podem inspecionar o formato inalterado da configuração do cabeçalho.
#1303 (issue no GitHub)AlteradoFuncionaO
recorddo checklist agora aceita uma verificação automática com sucesso cujo scansalvo é um scan audit.v2 em streaming; antes falhava com
'NoneType' object is not subscriptable, porque a auditoria fica no companion, e não na tabela legada do scan. Os formatos de registro aceitos estão documentados emseohead project checklist-record --help, no esquema MCP deseo_project_checklist_recorde emdocs/INPUTS.md.AlteradoFuncionaExecuta a suíte completa do toolkit uma vez no Python 3.15, em vez de uma matriz de
versões antigas, mantendo quatro grupos de testes verificados e cobertura combinada. Use a mesma versão estável do Python nos bootstraps de CI e de build de release.
AlteradoFuncionaA lista Work do Desktop lê todas as páginas do checklist (100 por requisição) em vez das
primeiras 50 linhas; Issues mostra o nome de cada verificação principal do registro, em vez de “Other check”.
AlteradoFuncionaO Work do Desktop lê todas as páginas do checklist, mas mostra o painel de tarefas do
projeto uma página por vez, então um checklist de qualquer tamanho não falha mais com “at most 100 rows”. O Desktop abre o scan que uma auditoria completa deixa para trás (o maior scan completo) quando o dono não escolheu um, e a descoberta do core também verifica o próprio ambiente do interpretador do Desktop (
sys.prefix) antes do PATH.AlteradoFuncionaConsolida verificações de auditoria retidas e melhorias nativas do desktop.
Preserva as configurações de orçamento de recursos sem alterar o cabeçalho congelado do scan, mantém a reanálise offline e a retomada seguras, e compartilha componentes nativos de configurações do projeto, tokens de tema e fontes incluídas. Remove insumos de design privados da árvore distribuída.
AlteradoFuncionaVincula as reverificações de remediação à política de assets efetiva validada,
preservando o cabeçalho original do scan e os bytes de origem.
AlteradoFuncionaA cobertura do checklist do projeto agora vincula relatórios audit.v2 em streaming:
report-build --projecteaudit-workflow --action reportanexam o snapshot do checklist às saídas xlsx, docx, csv, md e PDF de visão geral, em vez de gerar um relatório não vinculado. Um scan interrompido pelo orçamento de URLs (stopped_by_budget) é aceito como o último scan auditado do projeto, e o relatório informa o escopo limitado.report-build --inputaceita a chaveformat.report-build --project --format jsonem uma auditoria em streaming é recusado com uma explicação, porque o JSON é gravado tal como está e não pode carregar o snapshot do checklist.
10 de outubro de 2026
16 adicionado51 alteradoAlteradoFuncionaO monitor de scan do Desktop segue o painel de design ScanRun: porcentagem real a partir#1203
dos contadores fetched/found, barra de progresso de 10 px, limite de taxa do coletor e um placeholder honesto de gráfico de velocidade de 120 px (o histórico de taxa do core é rastreado em #1203).
#1203 (issue no GitHub)AlteradoFunciona
check_sampleemseohead/checks/custom_extract.pyexecuta extratores CSS, XPath e#1059regex sobre um único documento HTML salvo, sem scan nem requisição de rede. Cada resultado traz seus valores e um
#1059 (issue no GitHub)reasonpara um resultado vazio (no_match,empty_htmloubudget_exceeded), para que uma resposta vazia nunca seja apresentada como resultado limpo (#1059). É apenas uma chamada do core; ainda não há ferramenta de CLI nem MCP registrada, e buscar uma URL ao vivo foi deliberadamente deixado de fora.AlteradoFuncionaA verificação de sequência de paginação (
PAGINATION_SEQUENCE_ERROR) agora julga séries#1057com passo: quando um passo cobre a maioria dos passos de uma série, uma quebra desse passo é reportada (
#1057 (issue no GitHub)?page=1,3,5,8quebra em 5 para 8). Esquemas de offset irregulares e séries sem numeração continuam sem julgamento e são citados como ignorados.AdicionadoFuncionaNova verificação
INTERNAL_NOFOLLOW_OUTLINKS(aviso): lista cada página de origem que…#1052Nova verificação de rastreamento
#1052 (issue no GitHub)INTERNAL_NOFOLLOW_OUTLINKS(aviso): lista cada página de origem que tem links de saída internos comnofollow, com a contagem e uma amostra limitada de destinos. Fecha a lacuna em nível de página da linha “Internal Nofollow Outlinks” do Screaming Frog, que estava comopartial. Roda nos rastreamentos nativos e é ignorada pelo nome em execuções só de exportação e de lista de URLs.AlteradoFuncionaO parser lê declarações
<link rel="alternate">com mídia e semhreflang(uma URL#1051móvel separada) e as grava em
#1051 (issue no GitHub)parse_htmlcomomobile_alternates(#1051). A verificaçãoMobile Alternate Linkdo SF ainda é uma lacuna; a que compara o canonical da URL móvel ainda não foi escrita.AdicionadoFuncionaAdiciona a verificação
HREFLANG_UNLINKED_TARGET(aviso): um destino alternate de#1050hreflang que nenhum…
Adiciona a verificação
#1050 (issue no GitHub)HREFLANG_UNLINKED_TARGET(aviso): é reportado qualquer destino alternate de hreflang que nenhum link comum do rastreamento aponta. Assim, o “Unlinked Hreflang URLs” do Screaming Frog passa a ser coberto. A verificação lê o export All Hreflang e a coluna Internal:All Inlinks, do mesmo jeito queUNLINKED_CANONICAL; uma autorreferência não conta, e um rastreamento parcial retém o achado. O registro passa de 182 para 183 verificações.AlteradoFuncionaDimensionamento de imagens em rotas renderizadas: o render-check agora registra o tamanho#1049
intrínseco em pixels de cada imagem em relação à caixa renderizada e à razão de pixel do dispositivo (
#1049 (issue no GitHub)image_sizing: evidências de imagens superdimensionadas e ampliadas). É só evidência; ainda não há id de verificação no SF-analyzer, então “Incorrectly Sized Images” passa de gap para partial (#1049).AlteradoFuncionaSemantically Similar: o status continua
gap, e a nota agora declara o bloqueio.#1041O comando e a ferramenta MCP de similaridade semântica existem, mas nenhum adaptador de embeddings é distribuído e a execução do SF ainda não chama o módulo (#1041).
#1041 (issue no GitHub)AdicionadoFuncionaAdiciona a verificação
INTERNAL_LINK_SPONSORED_UGC(aviso): um link do mesmo site que#1040traz…
Adiciona a verificação
#1040 (issue no GitHub)INTERNAL_LINK_SPONSORED_UGC(aviso): um link do mesmo site comrel="sponsored"ourel="ugc"é reportado com o conjunto completo de tokens de rel. Ele precisa delink_attributes.capture, como as demais verificações de link baseadas em rel, e, sem isso, é reportado como não medido.AdicionadoFuncionaAdiciona o núcleo da geração de sitemap XML a partir de um scan retido:#1039
#1039 (issue no GitHub)select_indexablemantém só páginas HTML 200 autocanônicas, semnoindexe não bloqueadas pelo robots, e informa o motivo de cada URL excluída;render_sitemapsgrava um<urlset>ou arquivos divididos mais um<sitemapindex>a cada 50.000 URLs ou 52.428.800 bytes por arquivo. A exposição via CLI e MCP vem depois.AdicionadoFuncionaAdiciona
cloudflare-traffic(CLI) eseo_cloudflare_traffic(MCP): uma fonte somente#1026leitura do GraphQL Analytics da Cloudflare para o analisador de logs, quando os logs da origem não existem (#1026, #1009). Retorna bots × URLs × códigos de status × status de cache por dia, no formato de
#1026 (issue no GitHub)log-analyze, marcada comosource: cloudflare-aggregatedporque são dados agregados de borda, não logs brutos (sem IPs de clientes, então sem verificação por reverse DNS). Dias que atingem o limite de 10.000 linhas por página são divididos por janela de tempo; a chamada é contada no livro de gastos como provedor gratuito. O token vem deCLOUDFLARE_API_TOKENouSEOHEAD_CLOUDFLARE_TOKEN_FILEe nunca é exibido.AlteradoFuncionaAvaliador interno de achados do Search Console, ainda não ligado aos relatórios:#1025
#1025 (issue no GitHub)seohead/checks/search_console_findings.pycruza as páginas do rastreamento com um documento normalizado de evidências do GSC e avalia GSC_ORPHAN, NO_SEARCH_DATA e NON_INDEXABLE_WITH_SEARCH_DATA. Uma verificação é ignorada, com o motivo, quando o rastreamento é parcial, a janela está incompleta, a coleta é amostrada ou truncada, ou nenhuma evidência é fornecida; uma verificação ignorada nunca é reportada como limpa.AlteradoFunciona
crawl-enrichreporta quatro achados de web analytics a partir de um CSV offline#1024indexado por URL: URLs órfãs no analytics, páginas indexáveis sem dados de analytics, páginas não indexáveis com visitas e taxa de rejeição acima de 70%. As colunas nomeadas
#1024 (issue no GitHub)--visits-columne--bounce-columnselecionam os dados; uma coluna ausente é recusada pelo nome, valores ilegíveis são contados e nunca lidos como zero, e URLs órfãs do analytics são retidas em rastreamento parcial. A coleta ao vivo de Metrika/GA4 por URL ainda não está incluída (#990, #984).AlteradoFuncionaO mapa de cobertura de problemas do SF lista os quatro problemas de web analytics (Orphan#1024
URLs, Bounce Rate Above 70%, No GA Data, Non-Indexable with GA Data) como encontrados pelo
#1024 (issue no GitHub)crawl-enricha partir de um CSV offline, em vez de fora do escopo. Osf runainda não os emite.AlteradoFuncionaNúcleo de cobertura de laboratório para CSS e JavaScript não usados (#1023, fatia 1): um#1023
analisador puro recebe payloads de
#1023 (issue no GitHub)page.coveragedo Playwright e reporta, por recurso, os caracteres não usados, com um achado quando o recurso é majoritariamente não usado e grande. A coleta de cobertura a partir de uma página renderizada é a próxima fatia.AlteradoFuncionaVerificações de par AMP (#1020):
AMP_NON_200,AMP_MISSING_CANONICAL,#1020
#1020 (issue no GitHub)AMP_MISSING_RETURN_LINK,AMP_NON_INDEXABLE_CANONICALeAMP_INDEXABLEleem o alvo AMP que uma página desktop declara com<link rel="amphtml">. Só são avaliadas as páginas AMP que o rastreamento capturou; um alvo não capturado é ignorado e informado pelo nome. O rastreamento nativo agora registra o alvo resolvido na colunaAMP HTML. As outras dez regras AMP do SF continuam recusadas.AdicionadoFuncionaAdiciona
HTML_OVER_2MB, um teto absoluto de 2 MB para um documento HTML, separado de…#1019Adiciona
#1019 (issue no GitHub)HTML_OVER_2MB, um teto absoluto de 2 MB para um documento HTML, separado doLARGE_HTML, que é relativo à mediana. A regra “HTML Document Over 2MB” do Screaming Frog agora aponta para ele, em vez da regra de 200 KB.AdicionadoFuncionaAdiciona o aviso
URL_HAS_PARAMETERSà auditoria de rastreamento: uma página HTML#1018interna cuja URL tem parâmetros de query é reportada independentemente do estado do canonical.
#1018 (issue no GitHub)URL_HAS_PARAMSmantém o significado mais restrito, de ausência de canonical (#1018).AlteradoFuncionaDiretivas de robôs (#1017):
noodpenoydirlegados em meta robots ouX-Robots-Tag#1017agora geram os avisos
#1017 (issue no GitHub)NOODPeNOYDIRna auditoria do SF; antes eram listados como fora do escopo.none(noindex+nofollow) é coberta por testes de regressão tanto no caminho doX-Robots-Tagquanto no da meta tag.AdicionadoFuncionaNova verificação
JS_CONSOLE_ERRORS(SF “Pages with JavaScript Errors”): uma página cujo#1015console da renderização retida registrou erros. Lida offline a partir dos sidecars de console salvos de um scan nativo, sem nova renderização; um registro que não pode ser lido vira um skip declarado, não uma página limpa. Requer
#1015 (issue no GitHub)rendering.artifacts.console_errors.AlteradoFuncionaOs rastreamentos agora reportam quatro cabeçalhos de segurança ausentes por página HTML a#1013
partir da…
Os rastreamentos agora reportam quatro cabeçalhos de segurança ausentes por página HTML, a partir da resposta final armazenada:
#1013 (issue no GitHub)MISSING_CSP,MISSING_X_CONTENT_TYPE_OPTIONS,MISSING_X_FRAME_OPTIONS(satisfeita por uma diretivaframe-ancestorsdo CSP) eMISSING_REFERRER_POLICY. Páginas cujos cabeçalhos armazenados não podem ser interpretados são contadas como não medidas, e não como limpas; um rastreamento sem scan armazenado ignora essas páginas e informa o motivo.AdicionadoFuncionaAdiciona um validador para especificações fechadas de ação de página (
click,scroll,#1011
#1011 (issue no GitHub)wait_for_selector,wait_ms) com um orçamento de tempo estático para rastreamentos renderizados. Ele ainda não está ligado à renderização, então o comportamento do rastreamento não muda (#1011).AlteradoFunciona
log-analyzelê logs de acesso comprimidos em gzip (arquivos rotacionados#1009
#1009 (issue no GitHub)access.log.N.gze arquivos renomeados) diretamente, detectando o formato pelo conteúdo, e não pela extensão. Um arquivo truncado ou corrompido é reportado como erro, sem contagens parciais.AlteradoFunciona
scan-url-queryganha predefinições de visualização prontas (--preset, por exemplo#1007
#1007 (issue no GitHub)status_4xx,title_missing,title_over_60,h1_missing,noindex_meta) que se combinam por E com os filtros do usuário, e--export PATHcom--export-format csv|xlsxgrava todas as linhas correspondentes em um arquivo novo. A exportação é recusada acima de--export-max-rows(padrão 100.000) e nunca sobrescreve.AlteradoFuncionaAs regras de elegibilidade de resultados enriquecidos saíram do código Python e foram#1001
para
#1001 (issue no GitHub)seohead/data/rich_results_rules.json, um arquivo de dados versionado, empacotado com o pacote. O campoversiondesse arquivo é o valor gravado comorules_versionem cada veredito de resultado enriquecido; assim, mudar uma regra significa mudar dados, não código.AlteradoFuncionaOs vereditos de resultados enriquecidos (
check_schemae as verificações de evidências#1001estruturadas armazenadas) agora trazem
#1001 (issue no GitHub)rules_version, para que cada resultado informe qual conjunto de regras offline o produziu.AlteradoFuncionaDocumenta os seis scripts de manutenção e geração que não tinham referência na#997
documentação (
#997 (issue no GitHub)scripts/generate_project_catalogue.py,generate_registry_inventory.py,render_readme_visuals.py,linux_lifecycle_smoke.py,capacity_watchdog.py,profile_million_audit.py) emdocs/README.md, com o que cada um grava e quais rodam no CI (#997).AdicionadoFuncionaAdiciona o pipeline de núcleo semântico como
seohead/semantics, com banco SQLite#995próprio por projeto:
#995 (issue no GitHub)seohead semantics <stage> --project DIR(init, import, collect, clean, graph, exact, cluster, competitors, synonyms, report, excel, mine, sitematch, relevance, status, export), as ferramentas MCPseo_semantics_status,seo_semantics_run,seo_semantics_mineeseo_semantics_paid(as etapas pagas exigemconfirm_paid=true), clusterização Louvain atrás do novo extrasemantics, a skill empacotadasemantic-coree um projeto de exemplo sintético. As cobranças de provedor de uma etapa semântica são marcadas no diário de gastos compartilhado (#995).AlteradoFuncionaRemove o adaptador guiado do bot do Telegram
seohead/integrations/bot; recibos de#995entrega do monitor…
Remove o adaptador guiado do bot do Telegram
#995 (issue no GitHub)seohead/integrations/bot; os recibos de entrega do monitor agora ficam emseohead/projects/service_delivery.py(#995).AlteradoFunciona
scan-url-queryretornaclick_depth, o menor caminho de links internos a partir da#992página inicial do scan, como coluna, filtro e chave de ordenação. Páginas que nenhum link armazenado alcança ficam como
#992 (issue no GitHub)NULL(órfãs).crawl_depthnão muda e continua sendo a profundidade da fronteira, que é 0 para toda URL vinda de sitemap. Um scan que não reteve seus links falha comreason_code: click_depth_unavailable, em vez de reportar umNULLfalso. O valor é recalculado a cada consulta a partir da tabelalinks; gravá-lo como coluna indexada ao final do scan ainda está em aberto, porque exige uma decisão sobre a versão do schema (#992).AlteradoFunciona
scan-url-querye sua ferramenta MCP aceitam o argumento opcionalfacets(lista de#991grupos…
#991 (issue no GitHub)scan-url-querye sua ferramenta MCP aceitam o argumento opcionalfacets(uma lista de IDs de grupo, ouall), que retorna contagens por grupo (status_2xx–5xx,title_missing,canonical_missing,directives_noindex/nofollow,with_outlinks) sobre os mesmos filtros, em uma única passagem. Grupos que dependem de uma projeção (interno/externo, sitemap, título duplicado/tamanho, canonical autorreferente/outro) ainda não estão incluídos.AlteradoFuncionaVínculos de fontes do projeto, primeira fatia (#990):
project-sources-link,#990
#990 (issue no GitHub)project-sources-unlinkeproject-sources-list(CLI, além deseo_project_sources_link|unlink|listvia MCP) registram quais IDs de recursos do provedor um projeto local usa, emsources.jsonao lado deproject.json. Somente offline: sem descoberta, sem chamada a provedor, sem credenciais;project.jsonnunca é reescrito.AlteradoFuncionaRastreamento nativo: nova verificação IMG_BROKEN (#989, fatia 1) reporta alvos de <img>#989
que responderam 4xx/5xx, com a página de origem como evidência. Ela lê o grafo de recursos armazenado e ignora o caso com honestidade quando nenhuma imagem foi medida.
#989 (issue no GitHub)AdicionadoFuncionaAdicionado um classificador puro de soft 404 sobre o corpo da página armazenado#988
(
#988 (issue no GitHub)classify_stored_soft404): texto vazio, uma frase de erro em uma página com pouco conteúdo e uma correspondência por simhash com um template de 404. Ainda não está ligado ao rastreamento e não emite achados; esta é a primeira fatia da issue #988.AlteradoFuncionaRastreamentos nativos sondam alvos de canonical e hreflang que nenhum link alcançou, uma#987
vez por alvo, após o rastreamento (no máximo 5.000). Um alvo com 4xx/5xx ou que redireciona passa a reportar CANONICAL_TARGET_ERROR, CANONICAL_TO_REDIRECT ou HREFLANG_BROKEN_TARGET, como já acontecia com alvos rastreados (#987).
#987 (issue no GitHub)AlteradoFuncionaAchados de cadeia e loop de redirecionamento de um rastreamento nativo agora trazem o#985
caminho completo…
Os achados de cadeia e loop de redirecionamento de um rastreamento nativo agora trazem o caminho completo de saltos (
#985 (issue no GitHub)details.path), para que uma correção possa indicar cada salto a substituir. Refs #985.AlteradoFuncionaAchados de cadeia e loop de redirecionamento de um rastreamento nativo agora também#985
trazem…
Os achados de cadeia e loop de redirecionamento de um rastreamento nativo agora também trazem
#985 (issue no GitHub)details.inbound_links(links internos que ainda apontam para a primeira URL da cadeia, com âncoras, limitado a 20) einbound_links_count; sem um inventário all_inlinks, o campo ficanullcom um motivo. Refs #985.AlteradoFuncionaProjetos podem registrar um link para o seu núcleo semântico como fatos inseridos pelo#984
operador (
#984 (issue no GitHub)semcore_project,semcore_cluster_count,semcore_landing_mapping). O núcleo semântico continua no próprio banco e não é mesclado ao banco do projeto; a detecção nunca grava esses fatos, e um fato fornecido não pode alegar proveniência de detecção. Documentado emdocs/PROJECTS.md, na seção “Linking a semantic core” (parcial, #984).AlteradoFuncionaDesktop: a tela Link graph segue o design GraphFilters (canvas e painel de filtros).#975
O núcleo ainda não retorna o grafo de links completo, então o canvas mostra um estado de espera honesto e os filtros ficam inertes até lá (#975).
#975 (issue no GitHub)AlteradoFuncionaOAuth do GSC:
provider-auth --action cancel(CLI) eseo_provider_authaction=cancel…#964OAuth do GSC:
#964 (issue no GitHub)provider-auth --action cancel(CLI) eseo_provider_authcomaction=cancel(MCP) cancelam um registro pendente de fluxo de consentimento no navegador;statusinforma o fluxo pendente, quando existir. O registro do fluxo não guarda material de concessão e expira em dez minutos. Esta é a primeira fatia do #964: ainda não há início nem callback pelo navegador, então a superfície pública não cria nenhum fluxo e o acesso conectado continua sem ser afirmado.AlteradoFunciona
crawl-site --urls/--urls-file --projectagora registra o rastreamento por lista de URLs#962como uma execução de observer (
#962 (issue no GitHub)mode=list), que aparece emproject-observeeproject-scanscom seu artefato na pastascans/do projeto. Um coletor que falha é registrado comofailed; progresso e retomada de execuções de lista ainda não estão cobertos (#962).AdicionadoFuncionaAdiciona um esboço estruturado de playbook:
skill-listescenario-listretornam cada…#955Adiciona um esboço estruturado de playbook:
#955 (issue no GitHub)skill-listescenario-listretornam os passos ordenados de cada playbook, eskill-show/scenario-showacrescentam seus títulos e passos, para que um agente leia a forma do método sem interpretar markdown (#955). Novo comando de CLIscenario-liste ferramenta MCPseo_scenario_list.AlteradoFunciona
scan-content-searchaceita--kind regex(MCPkind="regex") para buscar em#954documentos retidos…
#954 (issue no GitHub)scan-content-searchaceita--kind regex(MCPkind="regex") para buscar nos documentos retidos com uma expressão regular do Python. Expressões inválidas são recusadas antes da varredura; um documento que excede o orçamento de tempo do regex é reportado como indisponível, nunca como ausente.AlteradoFuncionaChamadas ao DataForSEO com resposta perdida (erro de rede após o envio) são registradas…#949
Chamadas ao DataForSEO cuja resposta se perde (erro de rede depois de a requisição ser enviada) são registradas no diário com
#949 (issue no GitHub)cost_unknownecharge_status: unknown, assimspend-reportas lista como incertas, em vez de contá-las como chamada medida de custo zero (#949).AdicionadoFuncionaNovo comando
scan-structured-blocks(CLI) e ferramenta MCP#948
#948 (issue no GitHub)seo_scan_structured_blocks: para uma URL retida, descreve cada bloco JSON-LD (sua linha de origem, statusvalid/errors/warnings/parse_error, tipos, uma lista plana de propriedades, JSON de origem limitado e erros do grafo Schema.org). Funciona offline, apenas sobre o corpo completo da página retido; sem requisições de rede e sem alterações nos artefatos.AlteradoFunciona
crawl-sitesem projeto que grava um artefato de scan em SQLite agora compartilha seu#942teto de requisições por host com outros rastreamentos simultâneos do mesmo host, por meio de um cronograma privado no diretório de estado do usuário (
#942 (issue no GitHub)~/.config/seohead/.origin-pacing.sqlite). Antes, rastreamentos sem projeto rodavam sem controle de ritmo entre processos.AlteradoFuncionaPerfis do crawl-site (#941):
crawl-profile listmostra os nomes dos perfis salvos e…#941Perfis do crawl-site (#941):
#941 (issue no GitHub)crawl-profile listimprime os nomes dos perfis salvos ecrawl-profile delete NAMEremove um; ambos imprimem JSON e recusam nomes desconhecidos, com a lista dos perfis salvos.AlteradoFuncionaPerfis do crawl-site (#941):
--save-profile NAME --config FILEarmazena uma#941configuração validada…
Perfis do crawl-site (#941):
#941 (issue no GitHub)--save-profile NAME --config FILEarmazena uma configuração de rastreador validada como perfil nomeado (recusado quando traz cabeçalhos de credencial);--profile NAMErastreia com ele, e--setainda se aplica por cima. Os perfis ficam em~/.config/seohead/crawl-profilesou no diretório indicado porSEOHEAD_CRAWL_PROFILES. Listar e excluir perfis não fazem parte desta fatia.AlteradoFunciona
compare.v1agora lista páginas rastreadas em apenas um dos lados (url_sets:#938
#938 (issue no GitHub)only_in_before,only_in_after, contagens). Quando qualquer um dos rastreamentos é parcial,url_sets.unprovenfica verdadeiro, para que a ausência não seja apresentada como prova.AlteradoFuncionaCada salto de cadeias de redirecionamento e canonical registra status, próxima Location#930
(redirecionamentos)…
Cada salto de cadeias de redirecionamento e canonical registra o status, a próxima Location (redirecionamentos) e o tempo de resposta, para que a cadeia de uma URL seja lida a partir de evidências armazenadas, sem nova requisição (#930).
#930 (issue no GitHub)AlteradoFuncionaLoops de redirecionamento em cadeias por URL terminam com um passo marcador (
{"url": ..., "loop": true}#930) que não é buscado de novo, então a URL repetida fica visível nas evidências armazenadas;
#930 (issue no GitHub)final_urlcontinua apontando para o último salto buscado (#930).AdicionadoFuncionaExpõe as etapas create e scan-ingest do ledger de correções pelo CLI e pelo MCP…#926
Expõe as etapas de criação e de ingestão de scan do ledger de correções pelo CLI e pelo MCP:
#926 (issue no GitHub)remediation-create/seo_remediation_createcria um ledger novo e vazio, vinculado a um projeto (producer_buildprecisa ser um SHA Git completo de 40 caracteres; caminhos existentes são recusados), eremediation-ingest/seo_remediation_ingestingere uma auditoria salva como baseline/histórico sem rodar novo rastreamento (a reingestão da mesma revisão é idempotente). A lógica de armazenamento não muda; esta é a primeira fatia do #926.AlteradoFunciona
crawl_sitee as execuções de scan informameffective_max_requests_per_seconde#925
#925 (issue no GitHub)warnings: um aviso quando a taxa efetiva está acima de 2 req/s (o limite é estritamente maior que 2). A CLI imprime o mesmo aviso no stderr; o JSON no stdout e os padrões não mudam. O pacer não foi alterado.AlteradoFuncionaLog estruturado de eventos do projeto (
events.jsonl): eventos somente de acréscimo com#923source, actor e…
Log estruturado de eventos do projeto (
#923 (issue no GitHub)events.jsonl): eventos somente de acréscimo com campos source, actor e texto limitado, lidos do mais recente para o mais antigo, em páginas, com filtros por source e por texto. Expostos comoproject-event-append/project-event-pagena CLI eseo_project_event_append/seo_project_event_pagevia MCP (issue #923).AdicionadoFuncionaAdiciona o comando
ai-columne a ferramenta MCPseo_ai_column, a primeira fatia dacoluna personalizada com IA (refs #1012). Sobre páginas selecionadas de um scan retido, ou sobre itens normalizados fornecidos, prepara um plano limitado a partir do título, dos cabeçalhos e de um trecho do texto, com estimativa de tamanho baseada em caracteres (sem preço aplicado) e o escopo de consentimento que o agente chamador deve respeitar antes de qualquer envio. Valores por URL fornecidos são validados contra o hash de origem de cada página; valores ausentes, desatualizados, vazios ou grandes demais são reportados como tal e nunca preenchidos. Um CSV opcional, seguro contra fórmulas, exporta a coluna. O SEOHEAD não guarda chave de provedor e não faz nenhuma chamada a modelo.
AlteradoFuncionaCompartilha os abridores SQLite somente leitura e de escrita em
seohead.core.sqlite.Leitores de armazenamento, o importador de scans, o arquivo do GSC, o store de fontes, o store de junção de evidências e as duas classes de verificações agora abrem seus bancos por meio de um único helper para conexão, row factory e PRAGMAs. As duas classes de verificações fecham suas conexões explicitamente. O comportamento não muda; a normalização de caminhos e a ordem dos PRAGMAs permanecem em cada ponto de chamada.
AlteradoFuncionaCorreções de comportamento a partir de uma revisão de verificações, fontes de dados e
importação de evidências.
Mudanças de comportamento intencionais nesses caminhos: - Cadeias de redirecionamento com exatamente o limite de saltos (padrão 20) agora são resolvidas, em vez de reportadas como não resolvidas. A verificação de loop roda antes da verificação de limite, tanto na resolução de cadeias quanto nas caminhadas do caminho de saltos. - As verificações de confiança e citação do EEAT comparam hosts de destino com a porta (
netloc), como a lógica de host dos links internos. Sites com portas explícitas podem mudar resultados. - As verificações de palavras-chave do llms.txt casam termos ASCII como palavras inteiras, com plural opcional, entãorapid,ShowcaseeToolbarnão passam mais. Radicais em cirílico ainda casam como substring. - A captura de navegação mapeia o motivoreloadpararefresh_navigation. Motivos solicitados não mapeados, comopageBlockInterstitial, são registrados como observações de frame que o validador aceita. - A detecção de tecnologia trata uma implicação negada (["not", X]) como não implicando nada. - A importação de evidências rejeita nomes de métricas declarados em duplicidade, e a descoberta no Search Console usa as linhas que recebe. - As novas tentativas do Yandex Cloud dormem apenas entre uma tentativa e outra. As novas tentativas de query-analytics do Yandex Webmaster recuam antes da próxima tentativa. - A construção de schema repassa seutimeoutao cliente HTTP (padrão inalterado). - O armazenamento de recibos de entrega é criado com modo 0600 antes de o SQLite abri-lo. - Execuções de grafo semântico são serializadas, porque o conjunto de stop-words é estado de módulo. O runner semântico reporta erros de SQLite comook: false, em vez de lançar exceção. - O parser de erros do CrUX tolera corpos de resposta que não são objetos. - Removida uma guardasqlite3 is Noneinalcançável no ledger.AlteradoFuncionaDesktop: uma tela de Backlinks no layout design-v2.
Mostra o estado de espera honesto até que o núcleo armazene um perfil de links do projeto (#999); sem linhas de exemplo, e os filtros de grupo ficam desativados pelo mesmo motivo.
AlteradoFuncionaTela Crawler do desktop: adiciona o banner de resultados temporários com o endereço
selecionado e o texto de status (exibido só quando um rastreamento sem projeto retorna resultados), move as ações de limpar e salvar como projeto para um menu de overflow abaixo de 1000 px, mantém o campo de endereço e a faixa de abas de verificação utilizáveis em larguras estreitas, rola o cabeçalho de resultados em vez de espremer suas colunas e dá à barra de status da shell o mesmo padding direito de 8 px nos temas escuro e claro.
AlteradoFuncionaDesktop: telas de estados fatais por canvas (ErrorsCore): núcleo ausente, pouco espaço em
disco e sem permissão de escrita são mostrados a partir de fatos reais; a versão do núcleo e a integridade do scan mostram o selo neutro “indisponível nesta versão do núcleo” até que o núcleo os informe.
AlteradoFuncionaDesktop: o menu da linha de URL e o menu do cabeçalho de coluna, os grupos Edit, Scan e
Window da barra de menus, e os menus de contexto de achados e tarefas seguem o quadro Menus do canvas. Itens que o núcleo ainda não oferece continuam visíveis, desativados, com o motivo na dica de ferramenta.
AlteradoFuncionaDesktop: a tela “Export and reports” segue o canvas de design ProjExport (escolha de
dataset e formato, card de pasta, exportações recentes). Datasets e formatos que o núcleo ainda não consegue exportar (compare, tasks, PDF) aparecem como indisponíveis; o botão de execução fica desativado até que a exportação esteja ligada (#1191).
AlteradoFuncionaNeutraliza TAB e CR no início de identificadores do inventário de marketing e nos CSVs de
revisão de rascunhos de meta description, com o mesmo prefixo de apóstrofo já aplicado a
=,+,-e@. Ambas as proteções agora usamseohead.core.tabular.neutralize_formula.AlteradoFuncionaRequisições com credenciais de provedores (Arsenkin, Metrika, Yandex Cloud, IndexNow…
Requisições com credenciais a provedores (Arsenkin, Metrika, Yandex Cloud, IndexNow, Topvisor, destinos de BI) não seguem mais redirecionamentos HTTP, então o cabeçalho Authorization nunca é reenviado a outro host. Agora, um redirecionamento aparece como erro HTTP do provedor.
AdicionadoFuncionaAdiciona o formato de redirecionamento
csv(linhassource,target,301, com aspasquando necessário) ao
generate_rulee à ajuda da CLIredirects-generate. O formatowordpress-redirectionnão entrou porque a sintaxe de importação dele ainda não foi verificada (#998).AlteradoFuncionaO registro de execuções (
runs.jsonl) passa a rotacionar ao atingir um limite de tamanho(5 MiB por padrão;
SEOHEAD_RUN_LOG_MAX_BYTESaltera esse valor). A geração anterior é mantida comoruns.jsonl.1, e as leituras cobrem os dois arquivos, então as buscas de reuso ainda encontram chamadas recentes.AlteradoFuncionaOrganiza a aba Schema do card de URL no desktop na estrutura de canvas do design-v2
(lista de blocos, árvore de blocos, verificações). O núcleo devolve apenas a contagem de blocos JSON-LD por URL, então as colunas mostram estados de espera honestos, ligados à issue 948 do núcleo, e as contagens conhecidas continuam reais; nenhum bloco de exemplo é exibido.
9 de outubro de 2026
4 adicionado4 alteradoAdicionadoFuncionaAdiciona rótulos do terminal em RU/EN conforme o idioma, bloco de progresso da varredura#951
atual, seleção explícita…
Adiciona rótulos do terminal em RU/EN conforme o idioma, um bloco de progresso da varredura atual, seleção explícita de varredura e saída compacta do observador.
#951 (issue no GitHub)AlteradoFuncionaVarreduras salvas abrem de forma leve para leitura (#931).#931
#931 (issue no GitHub)scan-status,scan-url-detail,scan-link-inspecte o observador de projeto (project-scans,project-observe) não validam mais o artefato inteiro a cada abertura: verificam identidade, schema, versão e a linha de cabeçalho, obtêm os contadores via SQL (GROUP BYsobrepages_status) e informam isso em um campo aditivovalidation("light"ou"full"). A validação completa roda sob pedido (full_validation: trueemscan-status, ou--input '{"input_path": "...", "full_validation": true}'na CLI) ou quando os mesmos bytes (caminho, tamanho, mtime, estado do WAL, hash do cabeçalho) já foram validados completamente no processo. Uma varredura que falha nas verificações leves é recusada com o mesmo erro de antes, e todo caminho que grava ou registra evidências continua validando por completo.scan-url-detailexecuta a busca do alvo de redirecionamento (sem índice emresponses.effective_url_id) com orçamento de 0,5 s e informaresponses.redirect_target_lookupcomoskipped, em vez de varrer uma tabela grande.AdicionadoFuncionaAdiciona estado do MCP compartilhado e auditado, com revogação na inicialização e em#929
tempo real; expõe a presença segura de clientes pela CLI.
#929 (issue no GitHub)AdicionadoFuncionaAdiciona registro de clientes com permissão explícita, prévias, gravações atômicas,#929
backups verificados e restauração sem conflitos.
#929 (issue no GitHub)AdicionadoFuncionaAdicionado
scan-url-query(MCPseo_scan_url_query): leitura somente leitura,#927filtrada, ordenada e paginada no servidor, de toda a tabela de páginas de uma varredura salva, com
#927 (issue no GitHub)total,filtered_total(nullmaisfiltered_total_state: cappedquando a contagem excede seu orçamento de tempo), projeção de colunas, rótulos de cobertura da varredura, o formatoseohead.scan-url-query.v1e umreason_codelegível por máquina em toda falha. No máximo 200 linhas por chamada; ordenação porurl,status_code,page_ordinalouurl_idusa índices, e qualquer outra coluna exige um filtro que deixe no máximo 100.000 linhas (senão,sort_not_indexed). A varredura é aberta com verificação leve de identidade e de geração de schema, não com validação completa, e nunca é modificada.AlteradoFunciona
scan-link-inspect --view links(MCPseo_scan_link_inspect) pagina os links de saída#924ou de…
#924 (issue no GitHub)scan-link-inspect --view links(MCPseo_scan_link_inspect) pagina os hiperlinks de saída ou de entrada de uma URL, localizada pelo endereço e não pelo ID do documento: âncora,relcom as flags nofollow/sponsored/ugc, interno/externo, posição armazenada, atributotargete o status HTTP do outro lado (nullquando essa página não foi varrida). Filtra por tipo de link, follow, classe de status e trecho de texto;offset/limitaté 200;total/filtered_totalsão exatos ou marcados como capped. A varredura é aberta em modo somente leitura, sem validação completa, e as falhas trazem umreason_codelegível por máquina (url_not_found,scan_not_available,url_not_scanned,links_not_retained). Views e campos existentes não mudam.AlteradoFuncionaLayout do pacote reorganizado, sem shims de compatibilidade:
seohead.serversagora é…Layout do pacote reorganizado, sem shims de compatibilidade:
seohead.serversvirouseohead.mcp,seohead.toolsvirouseohead.checks,seohead.boteseohead.remote_apiforam paraseohead.integrations, a CLI fica no pacoteseohead.cli(comseohead.cli.terminal_progress), os módulos raiz compartilhados (models,graph,filesystem,runlog,verification,canonical_policy,input_contracts,job_contracts,provider_matrix) foram paraseohead.core, e a proveniência da build foi paraseohead._build.provenance.examples/econfig.example.jsonforam paradocs/examples/;PROVENANCE.mdeTRADEMARKS.mdforam paradocs/legal/. Os comandosseoheadesf-analyzernão mudaram; imports Python com os caminhos antigos precisam ser atualizados.AlteradoFuncionaReescreve o README em torno da instalação, de três caminhos de início rápido (do
rastreamento nativo ao relatório, das exportações offline do Screaming Frog, e de projeto com agente), de um mapa de funcionalidades por área, de uma visão geral da CLI, da configuração do MCP para Claude Code e Claude Desktop, do app desktop complementar e da fronteira entre o que é medido e o que não é, com capturas reais do terminal em
docs/assets/, feitas a partir de um fixture local de QA e do fixture sintético de exportação. Adicionadocs/CLI.md, que agrupa cada comando registrado por tarefa, com suas anotações de rede, escrita e pago (um teste de consistência agora falha se algum comando estiver faltando), edocs/WORKFLOWS.md, que documenta os comandos de execução de workflow, inbox e registro de monitor, antes apenas referenciados.
8 de outubro de 2026
1 adicionado10 alterado1 corrigidoCorrigidoFuncionaMantém a contabilização de bytes de HTML/DOM retidos local à transação e incremental, em#914
vez de reler todos os corpos armazenados a cada resposta única. Gravadores reabertos reconstroem o contador uma vez; deduplicação, rollback, savepoints e limites de retenção de corpos continuam intactos.
#914 (issue no GitHub)AlteradoFuncionaRelatórios de BI mantêm estados de coleta de provedores não verificados e sinalizadores#833
de qualidade como desconhecidos em métricas, cobertura e manifestos; amostragem, aplicação de limiares ou truncamento confirmados são parciais. Coortes de busca versus sessões exigem qualidade de coleta explícita, medições de contagem não negativas e escopos de origem qualificados, e mantêm a identidade de origem, a atribuição, o escopo de busca e a política de calendário de cada eixo. O pacote sintético de relatórios continua offline; a aceitação nativa do Sheets e do Looker segue separada.
#833 (issue no GitHub)AlteradoFuncionaVarreduras nativas de site em SQLite aceitam
max_urls=0para coletar até esgotar a fila…#818Varreduras nativas de site em SQLite aceitam
#818 (issue no GitHub)max_urls=0para coletar até a fila se esgotar, emax_depth=-1para desativar o limite de profundidade. Orçamentos de tempo e de HTTP continuam configuráveis separadamente, as guardas de armazenamento e a interrupção com retomada continuam ativas, e rotas materializadas legadas recusam uma população de URLs ilimitada.AlteradoFuncionaVarreduras somente de sitemap também preservam o limite de URLs desativado, em vez de#818
recusar seu primeiro…
Varreduras somente de sitemap também preservam o limite de URLs desativado, em vez de recusar o primeiro membro declarado quando o limite configurado é zero.
#818 (issue no GitHub)AlteradoFuncionaTaxas de requisição finitas explícitas acima do padrão de 2 requisições/s agora chegam à#818
faixa…
Taxas de requisição finitas explícitas acima do padrão de 2 requisições/s agora chegam também à faixa compartilhada de controle de ritmo por origem do projeto, além do limitador por varredura. Varreduras paralelas continuam reservando uma única agenda comum por host, em vez de multiplicar a taxa dele.
#818 (issue no GitHub)AlteradoFuncionaInterromper a análise nativa agora retorna um resultado interrompido explícito e#754
retomável, e mantém…
Interromper a análise nativa agora retorna um resultado interrompido explícito e retomável, e preserva as páginas capturadas, em vez de vazar um traceback de KeyboardInterrupt.
#754 (issue no GitHub)- AlteradoFuncionaRegenera o catálogo de projetos empacotado após a atualização do cenário do provedor Bing.#754 (issue no GitHub)
AlteradoFuncionaRejeita linhas malformadas de resposta do Bing Webmaster em vez de reportar um resultado#753
vazio como completo. Preserva os dados brutos da resposta, as linhas de origem e as contagens exatas devolvidas nas evidências salvas do provedor. Respostas de contagem de links mantêm o envelope de página documentado e reportam populações de várias páginas como parciais quando apenas uma página solicitada foi coletada.
#753 (issue no GitHub)AlteradoFuncionaReconhece o fallback compartilhado e já existente de conta de serviço do Google na#753
prontidão do GA4…
Reconhece o fallback compartilhado e já existente de conta de serviço do Google na prontidão do provedor GA4 e na descoberta de credenciais. Mantém as permissões da conta e o acesso aos alvos como não verificados, informa explicitamente credenciais malformadas e preserva o suporte a bearer token OAuth sem exigir as duas fontes.
#753 (issue no GitHub)AlteradoFuncionaVincula referências de capacidades headless ao isolamento de execução nativa e à#743
fronteira pública de roteamento do rastreamento externo, distinguindo implementação interna de disponibilidade em CLI/MCP, sem alterar o comportamento do rastreamento nem as alegações de capacidade.
#743 (issue no GitHub)AdicionadoFuncionaAdiciona paginação limitada de execuções finalizadas ao
project-observena CLI e noMCP, mantendo visível cada registro de execução em andamento armazenado. As páginas preservam os IDs exatos das execuções e a ordem reversa de admissão; contagens e metadados de retenção descrevem o armazenamento atual de 100 registros, não o histórico completo. A leitura nunca altera os estados de execução armazenados. Entradas JSON da CLI mantêm sua paginação e seu escopo de projeto, a menos que uma flag nomeada explícita os substitua.
AlteradoFuncionaTrata Ctrl+C em toda a transição nativa pós-coleta, inclusive ao abrir a varredura salva,
nas fases opcionais de acompanhamento, na análise e na finalização. Capturas não concluídas mantêm seus dados e o checkpoint retomável, e retornam um resultado JSON interrompido explícito. Uma interrupção após o commit final preserva o artefato concluído e informa a disponibilidade real da auditoria. A retomada explícita conclui o trabalho pós-coleta pendente mesmo com a fronteira esgotada, preservando as flags existentes de omissão de evidências e as entradas de sitemap retidas.
7 de outubro de 2026
4 adicionado4 alterado1 corrigidoAdicionadoFuncionaAdiciona um fixture descartável de aceitação em Linux para execução real de worker SSH#754
com chave…
Adiciona um fixture descartável de aceitação em Linux para execução real de worker via SSH com chave, downloads de API/TLS autenticados e ENOSPC do worker nativo em um tmpfs limitado apenas a jobs. Preserva a fila e as evidências, e exige um resultado explícito de não sucesso, sem reexecução, antes de um novo job de recuperação em JS. Esclarece as medições locais de ciclo de vida em relação às evidências de SSH e de contenção do sistema operacional.
#754 (issue no GitHub)AlteradoFuncionaPreserva evidências parciais de JavaScript em resultados de jobs remotos, inclusive a#754
correção somente leitura de jobs antigos já finalizados, sem alterar artefatos retidos nem orçamentos de renderização. Verifica o backup e a restauração reais da fila por meio de status autenticado, downloads e idempotência persistente; mantém o fixture de recuperação de duas páginas com renderização completa dentro de seus orçamentos finitos existentes.
#754 (issue no GitHub)AlteradoFuncionaRetorna exit 130 sem traceback quando SIGINT interrompe a saída JSON final após a
conclusão…
Retorna exit 130 sem traceback quando SIGINT interrompe a saída JSON final depois que um handler já foi concluído. Artefatos retidos permanecem inalterados; um fluxo de saída truncado nunca é reportado como sucesso.
AdicionadoFuncionaRegistra a estratégia de área de conteúdo usada para gerar hashes retidos e contagens de
tokens, em vez da estratégia de área padrão do parser. Seletores explícitos e exclusões agora têm proveniência de extração correspondente, mesmo quando o parser da página usou sua região padrão.
CorrigidoFuncionaMantém arquivos de staging SQLite nativos não publicados fora do histórico de varreduras
e dos candidatos à retenção; continua reportando arquivos publicados inválidos e permite varreduras ocultas comuns nomeadas pelo usuário.
AdicionadoFuncionaAdicionada coleta nativa SQLite somente de sitemap: um sitemap explícito define a
população completa de URLs solicitada, sem fallback para a página inicial, expansão por hiperlinks ou expansão por alvos de redirecionamento. Populações de sitemap vazias, incompletas ou acima do orçamento são interrompidas explicitamente, e a retomada reaproveita a população retida sem baixar o XML novamente.
AlteradoFuncionaPreserva registros de execução de projeto distintos para capturas nativas simultâneas e
compartilha, dentro do projeto, um gate de despacho local de 2 requisições/s para o mesmo host público; expõe a cada observador o tipo de origem de cada execução, a origem, a impressão digital da configuração e o limite de taxa agregado.
AdicionadoFuncionaAdiciona busca literal offline sobre HEAD, HTML, texto do corpo e marcação selecionada
por CSS retidos, com cobertura estática/renderizada explícita, corpos ausentes marcados como desconhecidos, trechos redigidos opcionais e paginação verificada por integridade em novos pacotes locais de resultados.
AlteradoFuncionaPreserva as configurações próprias de um rastreamento salvo do Screaming Frog ao
exportá-lo: o load-crawl não injeta mais a configuração atual do spider. Execuções ao vivo de spider e de lista continuam recebendo seus perfis explícitos por execução.
6 de outubro de 2026
9 adicionado14 alterado9 corrigidoAlteradoFuncionaFaz os testes próprios de captura externa resolverem de forma consistente seus virtual#896
hosts de loopback em todos os sistemas operacionais, sem alterar a política de rede de produção.
#896 (issue no GitHub)CorrigidoFuncionaMantém a entrada do terminal funcionando acima do limite de descritores do select, e#896
impede que Delete ou sequências de controle não suportadas cancelem notas não salvas.
#896 (issue no GitHub)AlteradoFuncionaRetém eventos versionados de navegação do navegador, com omissões limitadas, estado da#826
captura, política do renderizador e proveniência da URL. Distingue redirecionamentos HTTP observados, navegação por script, histórico ou fragmento no Chromium e causas desconhecidas, sem afirmar cliques humanos.
#826 (issue no GitHub)AdicionadoFuncionaExpõe as mesmas evidências em render-check e em relatórios limitados de scan-navigation#826
offline; preserva observações parciais quando a renderização falha.
#826 (issue no GitHub)AlteradoFuncionaPreserva a compatibilidade com rollback ao reter evidências de navegação em configurações#826
de…
Preserva a compatibilidade com rollback ao reter as evidências de navegação dentro de configurações de renderizador extensíveis; valida a codificação anterior, de pré-lançamento, sem enfraquecer as verificações de proveniência e sem tratar eventos observados como política do renderizador.
#826 (issue no GitHub)CorrigidoFuncionaMantém populações resumidas grandes e aninhadas, inclusive histogramas de profundidade,#818
em companions…
Mantém populações resumidas grandes e aninhadas, inclusive histogramas de profundidade, nos companions PDF completos, sem cobrá-las do orçamento limitado de metadados de exibição. Preserva destinos nomeados, marcadores (outlines) e links internos ao reescrever os links portáteis do companion, clonando o documento PDF completo.
#818 (issue no GitHub)AdicionadoFuncionaAdiciona
pdf_policy="overview-v1"explícito para requisições PDF audit.v2 retidas.#818A primeira página distingue as contagens completas de origem, exibidas e omitidas; prefixos de exibição determinísticos mantêm os estados e motivos de cobertura completos e linkam para o JSON completo de auditoria em streaming e para os companions CSV de achados, páginas e escopo. Um manifesto de hashes e contagens registra a proveniência e os limites de recursos. Destinos existentes são recusados, as exportações são preparadas em staging, e o marcador de conclusão do PDF só é publicado depois que todos os companions obrigatórios são validados. O comportamento padrão do PDF permanece inalterado: a visão geral nunca é selecionada silenciosamente nem descrita como um PDF exaustivo. Veja
#818 (issue no GitHub)docs/PDF_OVERVIEW.mdpara os limites exatos e a semântica de falhas.AdicionadoFuncionaAdiciona a operação somente leitura
page_viewsdo provedor GA4 por data, hostname e#782caminho…
Adiciona a operação somente leitura
#782 (issue no GitHub)page_viewsdo provedor GA4 para contagens de visualização por data, hostname e caminho visitado, independentemente das sessões de página de entrada. Reutiliza as credenciais, o transporte e o leitor paginado de relatórios do GA4 já existentes, com novas tentativas limitadas, resultados de cota e de permissão, metadados explícitos de fuso horário, amostragem e limiar, e vinculação de URL à origem declarada. As evidências restritas salvas são normalizadas pela junção e pelo pipeline de BI já existentes; tráfego ausente continua indisponível, em vez de virar zero.CorrigidoFuncionaMantém as atualizações do observador limitadas: reutiliza a cobertura por site, projeta a#777
atividade ao vivo do coletor separadamente e pagina os achados do audit.v2 sem materializar coleções não relacionadas do grafo.
#777 (issue no GitHub)AlteradoFuncionaPreserva todo coletor ativo em um histórico limitado e publica janelas de contadores#777
medidos…
Preserva todo coletor ativo em um histórico limitado, publica janelas de contadores medidos com carimbo de data/hora e distingue contadores não medidos de zero. Transmite o progresso verificado do Screaming Frog em tempo real, limitando os dois pipes de diagnóstico.
#777 (issue no GitHub)AdicionadoFuncionaAdiciona páginas somente leitura de checklist, de detalhe de tarefa e de varredura#777
retida, além de escopo explícito de métodos aplicáveis e uma projeção da inbox mais recente.
#777 (issue no GitHub)CorrigidoFuncionaMantém execuções de sitemap explicitamente associadas como distintas: contadores em#777
andamento permanecem desconhecidos, e as medições finais contam os documentos de sitemap analisados separadamente das URLs declaradas, dos erros e dos truncamentos.
#777 (issue no GitHub)AlteradoFuncionaObserva recibos de artefatos de checklist por meio de metadados de identidade de arquivo#777
protegidos, sem recalcular o hash dos bytes retidos a cada atualização. Leituras explícitas de cobertura mantêm a verificação dos bytes; evidências alteradas ou legadas e não verificadas continuam visíveis como desatualizadas ou não verificadas.
#777 (issue no GitHub)CorrigidoFuncionaMantém recibos históricos de prioridade vinculados ao escopo original de seus itens#777
quando novas tarefas são adicionadas após a preparação, e valida cada candidato completo de cobertura antes da publicação atômica. Leituras de detalhe de concorrentes com escopo preservam a verificação passiva somente de metadados.
#777 (issue no GitHub)AdicionadoFuncionaAdiciona comparação explícita de auditorias salvas em disco, com resultados NDJSON#762
completos, ordenação determinística, identidades de origem, checksums por arquivo e conservação de achados antes e depois. Comparações grandes de audit.v2 exigem um novo diretório de saída; identidades duplicadas e colisões na correspondência de URLs falham, em vez de perder linhas.
#762 (issue no GitHub)CorrigidoFuncionaMantém a verificação direcionada de audit.v2 limitada quando há linhas duplicadas, retém#762
a identidade de varredura validada nos documentos selecionados e recusa identidades conflitantes, ou rastreamentos posteriores inválidos, como prova de correção.
#762 (issue no GitHub)AdicionadoFuncionaAdiciona compressão gzip em streaming, opcional, para arquivos NDJSON completos de#762
compare.v2, com bytes comprimidos determinísticos, hashes exatos do arquivo comprimido e contagens decodificadas de linhas e bytes. Adiciona um leitor limitado que valida exportações simples ou em gzip e rejeita fluxos danificados ou contagens divergentes do manifesto; a saída simples continua sendo o padrão.
#762 (issue no GitHub)CorrigidoFuncionaMantém a compatibilidade da comparação de corpus salvo como desconhecida quando uma das#762
flags de completude está ausente, e avisa explicitamente sobre corpora parciais conhecidos. Preserva os IDs e os motivos de verificações puladas e desativadas junto com as variações de achados, para que medições ausentes não sejam apresentadas como correção verificada.
#762 (issue no GitHub)AlteradoFuncionaFaz o observador de projeto no terminal navegar por detalhes legíveis de tarefa, método,#752
dados…
Faz o observador de projeto no terminal navegar por detalhes legíveis de tarefas, métodos, dados estruturados, varreduras, execuções, inbox e evidências retidas, com páginas limitadas e cobertura de escopo honesta. Leituras de armazenamento e envios explícitos de notas ficam fora do loop de entrada.
#752 (issue no GitHub)AlteradoFuncionaPreserva rascunhos separados de notas e de objetivos durante a sessão, com edição por#752
cursor…
Preserva rascunhos separados de notas e de objetivos durante a sessão, oferece edição com cursor, mantém colagens grandes sem truncar, exibe recibos de salvamento em todos os layouts e imprime rascunhos não salvos após uma saída normal do terminal, para recuperação.
#752 (issue no GitHub)AdicionadoFuncionaAdiciona navegação explícita de cobertura e artefatos do próprio site e dos concorrentes,#752
mantém o site selecionado nas páginas de varredura e de achados, exibe sugestões recentes de concorrentes baseadas em notas e mantém o progresso medido da coleta visível em terminais compactos. Amostras antigas não são mais animadas como progresso ao vivo.
#752 (issue no GitHub)AdicionadoFuncionaAdiciona um inventário versionado de capacidades headless gerado das configurações reais#743
do rastreador…
Adiciona um inventário versionado de capacidades headless, gerado a partir das configurações reais do rastreador, com referências de implementação, CLI/MCP, testes e lacunas de aceitação explícitas.
#743 (issue no GitHub)AdicionadoFuncionaAdiciona um benchmark HTML/JavaScript opcional, em origem própria, com fases congeladas e#743
orçamentos de memória da árvore de processos, de disco e de recuperação. Navegadores reais criam os DOMs medidos; o perfil, por si só, não estabelece a capacidade de JavaScript de sites grandes.
#743 (issue no GitHub)CorrigidoFuncionaCorrige o argumento de streaming não suportado na ponte JavaScript nativa e preserva#743
contadores de renderização já observados durante o cancelamento gracioso e a retomada.
#743 (issue no GitHub)AlteradoFuncionaPermite que o log-scan consuma caminhos de varredura nativa retidos e companions do#711
audit.v2 sem materializar o JSON legado. Transmite achados de consistência, mantém a pertinência de páginas nativas e a deduplicação de achados em disco, preserva contagens exatas de anomalias e limita apenas os exemplos. Informa explicitamente a ausência do rastro nativo de decisões de exclusão.
#711 (issue no GitHub)AlteradoFuncionaReconhece um achado de lastmod do sitemap em todo o site na origem sem caminho do site#711
medido, quando nenhuma página inicial foi rastreada. A exceção exige evidência de resumo do sitemap correspondente e não isenta achados de página, hosts não relacionados ou caminhos de destino não suportados.
#711 (issue no GitHub)AlteradoFuncionaCompara varreduras audit.v2 retidas por chave exata e índice ordinal, sem duplicar
payloads…
Compara varreduras audit.v2 retidas por meio de uma chave exata e de um índice ordinal, sem duplicar payloads de páginas e achados no armazenamento temporário do SQLite. Linhas completas, exportações determinísticas simples ou gzip, identidades de origem e entradas legadas continuam suportadas. Os leitores de auditoria fixam o snapshot validado por meio de leituras indexadas de linhas.
AlteradoFuncionaReverter saídas de comparação em falha tardia de publicação e recusar destinos…
Reverte os membros de saída de comparação próprios em caso de falha tardia na publicação e recusa destinos criados em concorrência; o manifesto continua sendo o marcador final de confirmação do pacote.
AlteradoFuncionaDescrever a entrada pública como engenharia de SEO configurável com agentes e…
Faz a página de entrada pública descrever a engenharia de SEO configurável com agentes e vincula toda a superfície de funcionalidades aos seus métodos, entradas e limites de evidência. Corrige orientações desatualizadas sobre o modo nativo/SF, a cobertura de projetos e a remediação. Documenta separadamente a planilha de trabalho do desenvolvedor, escrita por agentes e distinta da saída factual de relatórios, incluindo critérios de aceitação revisados e links de origem.
CorrigidoFuncionaRestaurar a paridade do relatório legível entre entradas audit.v2 em streaming e o JSON…
O Markdown agora usa um único renderizador incremental, incluindo explicações de verificações indisponíveis, registros de exclusão e notas finais de cobertura. O XLSX compartilha um único layout de metadados e grava problemas e páginas em planilhas somente de gravação, de tamanho limitado, preservando todas as planilhas, colunas, filtros, gráficos e contagens de origem. Problemas suprimidos retidos podem ser reproduzidos sem materializar a coleção, e URLs de execução ausentes usam o mesmo fallback para a primeira página.
AlteradoFuncionaRotular a proveniência de auditorias em PDF independentemente do esquema compartilhado…
Rotula a proveniência das auditorias em PDF independentemente do esquema compartilhado de auditoria: rastreador nativo, exportações do Screaming Frog ou um coletor SF explicitamente identificado, e coletor desconhecido. Uma auditoria nativa que usa o esquema do SF Analyzer não recebe mais um cabeçalho do Screaming Frog.
AlteradoFuncionaTransmitir linhas de escopo de problemas suprimidos para CSV em vez de acumular…
Transmite as linhas de escopo de problemas suprimidos para CSV, em vez de acumular suas explicações renderizadas na memória. As exportações completas de exclusão mantêm a ordem e os fatos de origem, enquanto a alocação permanece limitada para grandes coleções de exclusões retidas.
5 de outubro de 2026
1 alteradoAlteradoFuncionaConciliar cada linha de lacuna de cobertura pela célula Mode real, validar…#830
Concilia cada linha de lacuna de cobertura a partir da sua célula Mode real, valida as referências de verificações e ferramentas cobertas contra os registros públicos e gera prioridades a partir das linhas não resolvidas.
#830 (issue no GitHub)
4 de outubro de 2026
56 adicionado75 alterado5 corrigidoAdicionadoFuncionaAdicionar uma projeção offline de progresso GSC de marca e sem marca, sensível ao Unicode…#880
Adiciona uma projeção offline de progresso GSC de marca e sem marca, com aliases explícitos sensíveis ao Unicode, CTR ponderado compatível e faixas rotuladas de posição média.
#880 (issue no GitHub)AdicionadoFuncionaAdicionado agrupamento opcional de tarefas com
check_assignmentpara URLs de template…#878Adicionado agrupamento opcional de tarefas com
#878 (issue no GitHub)check_assignmentpara mapeamentos declarados de URL de template ou componente, ou para segmentos de crawl validados. Itens agrupados mantêm contagens de ocorrências e de URLs, evidências limitadas, proveniência do agrupamento, escopo de verificação e os estados declarado, candidato, confirmado ou não atribuído.AdicionadoFuncionaAdicionar mapas opcionais de comparação de releases
url-correspondence.v1com origem e#877URLs…
Adiciona mapas opcionais de comparação de releases
#877 (issue no GitHub)url-correspondence.v1, com pares declarados de origem e URL, recusa de colisões, proveniência de dados das páginas e saídarelease_review.v1.AdicionadoFuncionaAdicionar uma projeção offline de coortes de publicação qualificada por evidências…#876
Adiciona uma projeção offline de coortes de publicação qualificada por evidências, com proveniência de datas, inventário de autores, observações de provedores rotuladas e janelas de idade opcionais.
#876 (issue no GitHub)AdicionadoFuncionaAdicionar um inventário offline de CTAs e formulários incorporados para HTML fornecido…#875
Adiciona um inventário offline de CTAs e formulários incorporados para HTML fornecido, preservando cada ocorrência, com destinos ausentes anuláveis, saída JSON e CSV limitada e cobertura explícita de corpo incompleto.
#875 (issue no GitHub)AlteradoFuncionaPreservar a classificação de timeout remoto ao ocultar erros de transporte e reproduzir…#866
Preserva a classificação de timeout remoto ao ocultar erros de transporte, e reproduz com segurança manifestos de proxy direto para verificação direcionada.
#866 (issue no GitHub)AlteradoFuncionaLer evidências de atribuição do grafo de links SQL retido, preservar atribuição nula…#866
Lê as evidências de atribuição a partir do grafo de links SQL retido, preserva a atribuição nula explícita na exportação e mantém as verificações de links externos armazenadas em spool durante a retomada.
#866 (issue no GitHub)AlteradoFuncionaRegenerar catálogos integrados e contratos de relatório; instalar o validador de PDF com#866
o…
Regenera catálogos integrados e contratos de relatório; instala o validador de PDF com o extra all e mantém os testes com navegador falso independentes da seleção do Chrome local.
#866 (issue no GitHub)AdicionadoFuncionaAdicionar um plano de carga offline opcional para BigQuery com tabelas versionadas…#837
Adiciona um plano de carga offline opcional para BigQuery que expõe tabelas com versão de esquema, requisitos de faturamento e pré-requisitos explícitos de autorização, sem acesso à nuvem.
#837 (issue no GitHub)AdicionadoFuncionaAdicionar um transporte REST do BigQuery com lista de permissões e jobs de carga em#837
staging…
Adiciona um transporte REST do BigQuery com lista de permissões, jobs de carga em staging determinísticos, reconciliação de contagem de linhas e publicação atômica documentada por tabela, em vez de uma transação entre tabelas que não existe.
#837 (issue no GitHub)AlteradoFuncionaExigir uma aprovação
cost_authorizeddo BigQuery, separada e controlada pelo host…#837Exige uma aprovação
#837 (issue no GitHub)cost_authorizeddo BigQuery, separada e controlada pelo host, antes de qualquer token, verificação de dataset ou gravação em staging.AdicionadoFuncionaAdicionar um construtor local e validado de link de cópia do Looker Studio para o…#836
Adiciona um construtor local e validado de link de cópia do Looker Studio para o pacote sintético de cinco páginas de relatórios. Ele exige um ID de relatório original e aliases exatos de fonte do Sheets ou do BigQuery, sem publicar relatório nem inventar um modelo.
#836 (issue no GitHub)AdicionadoFuncionaAdicionar o fixture sintético de planilhas versionado#836
(
examples/reporting-pack/worksheets/)…Adiciona o fixture sintético de planilhas versionado (
#836 (issue no GitHub)examples/reporting-pack/worksheets/): um CSV por dataset do BI, mais o manifesto, gerado de forma byte a byte determinística a partir deexamples/audit.jsone de duas entradas sintéticas de GSC e GA4. Demonstra os estados de zero medido, suprimido ou ausente, somente externo, não chaveável, verificação ignorada, dataset indisponível e quadrante incompleto, e é verificado como reproduzível porscripts/generate_reporting_pack_worksheets.py --check.AdicionadoFuncionaAdicionar
examples/reporting-pack/SETUP.md: o guia operacional do proprietário para…#836Adiciona
#836 (issue no GitHub)examples/reporting-pack/SETUP.md: o guia operacional do lado do proprietário para importar as seis planilhas no Google Sheets, conectar os aliases reservados de fontes de dados, montar as cinco páginas do blueprint com os controles declarados e os campos calculados, ativar a permissão de cópia e verificar uma cópia nova. O modelo nativo do Looker Studio continua sendo uma etapa externa autorizada pelo proprietário; nenhum ID de relatório, link ou gravação no Google é incluído.AlteradoFuncionaPreservar os nomes de partição, contagens e checksums do pacote BI gerado para que o…#836
Preserva os nomes de partição, as contagens e os checksums do pacote BI gerado, para que o fixture de planilhas passe na verificação prévia existente do Sheets e nos consumidores de exportação filtrada. Documenta os campos de alias separados da API de Linking e exige verificação de cópia nova pela URL gerada, sem reparo manual das fontes.
#836 (issue no GitHub)AlteradoFuncionaRejeitar aliases duplicados da API de Linking após normalização de espaços e retornar…#836
Rejeita aliases duplicados da API de Linking após normalização de espaços e retorna os aliases exatos usados nos parâmetros de URL. Define IDs compartilhados de campos de execução, controles de data de provedores agrupados e gráficos de cobertura que excluem populações sobrepostas. A criação do modelo nativo e a verificação de cópia nova continuam como requisitos externos de aceitação.
#836 (issue no GitHub)AdicionadoFuncionaAdicionar linhas explícitas de coorte de URL com evidência qualificada aos pacotes BI#835
locais…
Adiciona linhas explícitas de coorte de URL com evidência qualificada aos pacotes BI locais, incluindo quadrantes do Search Console e do GA4 seguros para zero medido, apenas para observações completas, compatíveis e um para um.
#835 (issue no GitHub)AlteradoFuncionaCalcular parcelas observadas de inlinks a partir de páginas de origem únicas no escopo…#835
Calcula as parcelas observadas de inlinks a partir de páginas de origem únicas no escopo, com extração HTML concluída, preservando as ocorrências repetidas separadamente e rotulando populações parciais.
#835 (issue no GitHub)AdicionadoFuncionaAdicionar pacotes BI offline tipados e determinísticos para scans e auditorias salvos…#834
Adiciona pacotes BI offline tipados e determinísticos para scans e auditorias salvos e para evidências de provedores fornecidas, com limites de partição, estados nulos, conservação de linhas e células CSV protegidas contra injeção de fórmulas.
#834 (issue no GitHub)AlteradoFuncionaPreservar problemas de companions audit.v2 limitados, cruzar até 1.000.000 de URLs…#834
Preserva os problemas de companions audit.v2 limitados, cruza até 1.000.000 de URLs de scan retidas por meio de um artefato de evidências SQLite durável e transmite esse artefato para o BI sem materializar listas de páginas ou de URLs correspondentes. Isso não entrega um modelo copiável do Looker Studio.
#834 (issue no GitHub)AlteradoFuncionaProjetar grupos de problemas, candidatos de quadrantes de provedores e fontes de inlink…#834
Projeta grupos de problemas, candidatos de quadrantes de provedores e fontes de inlink elegíveis por meio de um índice SQLite descartável e limitado. Mantém as dimensões dinâmicas de provedores válidas nas exportações selecionadas e nos planos offline de Sheets e BigQuery, e limita a quantidade de partições e o consumo de disco.
#834 (issue no GitHub)AlteradoFuncionaPreservar URLs-alvo e mensagens de problemas de auditoria nativa como colunas BI tipadas…#834
Preserva as URLs-alvo e as mensagens dos problemas de auditoria nativa como colunas BI tipadas, e não apenas dentro do JSON de origem retido, para que seleções exatas de URLs conservem os problemas afetados.
#834 (issue no GitHub)AdicionadoFuncionaAdicionar
scan-fragment-links(seo_scan_fragment_links) e a verificação#827BROKEN_BOOKMARK…Adiciona
#827 (issue no GitHub)scan-fragment-links(seo_scan_fragment_links) e a verificação de auditoriaBROKEN_BOOKMARK: cada<a href>com fragmento no HTML ou DOM completo retido é resolvido contra os IDs de elementos e os alvos<a name>do documento de destino, usando o algoritmo WHATWG de rolagem até o fragmento (o fragmento serializado é testado primeiro contra IDs e nomes; depois, o valor decodificado em percentual e UTF-8 é testado contra os dois;+continua sendo um sinal de mais literal;#e#topresolvem para o topo do documento). As representações estática, renderizada e de fragmento legado são avaliadas de forma independente, as regras de redirecionamento e de<base href>são respeitadas, e uma query string diferente significa um documento diferente. Corpos ausentes, truncados, não suportados, com falha ou que esgotaram o orçamento são registrados como ignorados, com o motivo indicado, nunca como links quebrados. Exportações do Screaming Frog e importações legadas indicam que a verificação está indisponível, em vez de afirmar que passou limpa. Os resultados são limitados e paginados de forma determinística (total,returned,offset/limit,next_offset, estado de cobertura), idênticos na CLI, no MCP e no resumo de auditoria do scan retido. Nada é buscado: a avaliação é somente leitura e offline.AlteradoFuncionaValidar links de retorno de hreflang nativos contra declarações completas de alvos#825
retidas…
Valida links de retorno de hreflang nativos contra declarações completas de alvos retidas, distinguindo um retorno ausente conhecido de um alvo não rastreado ou com corpo indisponível. Informa alternativas observadas com noindex, preserva rótulos brutos e identidades de URL normalizadas com contexto de duplicidade e conflito, e marca relações parciais de população como não medidas. As superfícies existentes de auditoria, CLI, MCP e relatório trazem os mesmos problemas, sem buscar nada adicional.
#825 (issue no GitHub)AdicionadoFuncionaAdicionar
CANONICAL_TARGET_ERRORpara informar alvos canônicos buscados com 4xx/5xx…#824Adiciona
#824 (issue no GitHub)CANONICAL_TARGET_ERRORpara informar alvos canônicos buscados que retornam 4xx ou 5xx, com evidências de origem, alvo, resposta e indexabilidade. Alvos desconhecidos ou com status incompleto continuam indisponíveis; variantes 2xx conhecidas removem o veredito de erro, e alvos 3xx permanecem emCANONICAL_TO_REDIRECT.AdicionadoFuncionaAdicionar
CANONICAL_HOMEPAGE_GROUPpara grupos de pelo menos três páginas indexáveis…#824Adiciona
#824 (issue no GitHub)CANONICAL_HOMEPAGE_GROUPpara grupos de pelo menos três páginas buscadas e indexáveis, em dois ou mais trechos de caminho, com títulos e H1s distintos, que apontam canonicamente para a homepage buscada. Autorreferência da home, URLs com query, paginação reconhecível, padrões configurados de paginação ou filtro, evidência incompleta da homepage e rastreamentos nativos parciais não geram problema em nível de site.AdicionadoFuncionaAdicionar evidências objetivas de autoria, datas e páginas de confiança às auditorias…#823
Adiciona evidências objetivas de autoria, datas e páginas de confiança às auditorias de escopo (issue #823): oito verificações de severidade informativa em
#823 (issue no GitHub)seohead/sf/core/eeat.py, que relatam o que um crawl pode observar, e nunca uma pontuação de E-E-A-T.NO_AUTHOR_BYLINEeNO_CONTENT_DATESdisparam apenas em páginas com cara de conteúdo (um tipo de artigo em JSON-LD,og:type=article, um elemento<article>ou um caminho de conteúdo convencional) e citam os portadores que leem (meta_author,rel_author,itemprop=author, classebyline,<time datetime>,author,datePublishededateModifieddo JSON-LD, um caminho de URL com formato de data), cada um com uma confiança declarada.MISSING_ABOUT_PAGE,MISSING_CONTACT_PAGE,MISSING_PRIVACY_POLICYeMISSING_TERMS_PAGEinformam um dos estadosfound_indexable(silencioso),found_non_indexable,found_error,discovered_not_crawledounot_discovered, para que uma página que existe mas não responde nunca pareça igual a uma que ninguém linkou.FEW_CITATIONSinforma apenas o que as posições dos links conseguem comprovar (um link de saída dentro do texto do corpo, ou uma contagem declarada de zero), eYMYL_REVIEW_CANDIDATEsinaliza correspondências determinísticas de palavra inteira em caminho ou título para revisão humana, nunca uma classificação. O não medido permanece distinto do ausente em todo o processo: uma página cujo corpo nunca foi analisado mantémtrust_signalscomo NULL e é contada no motivo do ignorado;summary.trust_evidenceregistra o escopo avaliado, o estado por tipo de página e uma ressalva de crawl parcial para vereditosnot_discovered.AlteradoFuncionaClassificar LCP, INP e CLS p75 de campo do CrUX na janela atual contra limites oficiais…#822
Classifica o p75 de LCP, INP e CLS de campo da janela atual do CrUX contra limites oficiais versionados, mantendo o escopo de URL ou origem, fator de forma e período de coleta. Evidência de campo ausente, incompleta ou com falha permanece indisponível ou parcial.
#822 (issue no GitHub)AdicionadoFuncionaAdicionar amostragem explícita e limitada de URLs com cache privado opcional e aceitar…#822
Adiciona amostragem explícita e limitada de URLs com cache privado opcional, e aceita evidências salvas do CrUX em auditorias de sites e relatórios, sem requisições automáticas ao provedor. Limita os bytes de resposta e de cache, e rejeita contagens de amostra salvas inconsistentes ou registros de URL repetidos, em vez de informar cobertura de campo completa.
#822 (issue no GitHub)AlteradoFuncionaDocumentar o limite atual da CLI Docker de execução única, separado do serviço remoto…#820
Documenta o limite atual da CLI Docker de execução única separadamente da API remota e do serviço de worker opcionais, construídos explicitamente.
#820 (issue no GitHub)AdicionadoFuncionaAdicionar a receita de execução SSH em workspace persistente e explicar que o estado…#820
Adiciona a receita de execução SSH em workspace persistente e explica que o estado de saída e os artefatos da CLI não são uma verificação de saúde de serviço HTTP.
#820 (issue no GitHub)AlteradoFuncionaAdmitir configurações explícitas de crawl SQLite nativo de até 1.000.000 de URLs…#818
Admite configurações explícitas de crawl SQLite nativo de até 1.000.000 de URLs, com orçamento separado de 2.000.000 de requisições HTTP e o perfil sintético somente de armazenamento já existente. CLI, MCP, fila remota e workers preservam os mesmos orçamentos declarados. APIs legadas e de lista materializadas mantêm um limite de segurança explícito de 50.000 URLs. Robots da lista, retentativas, saltos de redirecionamento e de canonical agora compartilham o orçamento de requisições. Auditorias nativas e reanálise offline usam o caminho audit.v2 limitado, sem a antiga recusa de ponte de 10.000 páginas ou 20.000 formulários. Contadores do gravador transacional evitam reescanear a fronteira de rastreamento crescente a cada lote. Um driver manual de aceitação registra as identidades das fontes carregadas, a interrupção e a retomada, e os consumidores downstream; a admissão, por si só, não é evidência de aceitação concluída de um milhão de URLs.
#818 (issue no GitHub)AlteradoFuncionaExecutar cada etapa manual de aceitação nativa sob um watchdog de recursos de subprocesso…#818
Executa cada etapa manual de aceitação nativa sob um watchdog de recursos de subprocesso, retém artefatos interrompidos, verifica cada linha e a cobertura de tarefas em CSV e XLSX, e testa separadamente o HTTP em loopback próprio e protegido, com o pacing padrão inalterado.
#818 (issue no GitHub)AlteradoFuncionaPermitir durações de crawl remoto explicitamente autorizadas de até 14 dias…#818
Permite durações de crawl remoto explicitamente autorizadas de até 14 dias, mantendo o padrão de uma hora e os orçamentos independentes de projeto, requisições, disco, lease e renderização. Isso permite que um alvo de um milhão de páginas caiba em sua taxa de requisições polida e inalterada. Valores acima do teto de duração e tipos inválidos falham antes da coleta.
#818 (issue no GitHub)AlteradoFuncionaA reanálise offline usa um prazo novo para cada operação de execute e fetch do SQLite,#818
preservando a interrupção e o cancelamento de consultas sem cobrar o parsing em Python nem as gravações derivadas do prazo original de validação na abertura do scan.
#818 (issue no GitHub)AlteradoFuncionaO
crawl-site --out-dirlegado agora mantém evidências em sidecars JSONL…#817O
#817 (issue no GitHub)crawl-site --out-dirlegado agora mantém evidências de páginas, links e formulários em sidecars JSONL somente de anexação durante a coleta e a retomada, em vez de reter listas duplicadas na memória. Checkpoints verificam as contagens dos sidecars, e checkpoints v4 antigos com formulários inline migram sem perder problemas de formulário. A ponte de auditoria existente nomeia seus limites de materialização de páginas, formulários e links, e preserva as evidências coletadas quando uma auditoria fica indisponível. Um relatório anterior é mantido sob um nome de arquivo obsoleto, em vez de ser apresentado como execução atual. A escalada nativa de JavaScript lê os registros de páginas por meio de uma view SQLite re-iterável, em vez de reconstruir todos os objetos de página. A transmissão completa de auditorias grandes continua rastreada em #816 e #817.AlteradoFuncionaArmazenar auditorias nativas grandes em companions audit.v2 ordenados, sem descartar…#817
Armazena auditorias nativas grandes em companions audit.v2 ordenados, em vez de descartar a disponibilidade da auditoria.
#817 (issue no GitHub)AlteradoFuncionaTransmitir a normalização de auditoria nativa para o seu contexto, sem lista#817
intermediária de registros.
#817 (issue no GitHub)CorrigidoFuncionaManter mapas de páginas da auditoria nativa e métricas derivadas por página em um…#817
Mantém mapas de páginas da auditoria nativa e métricas derivadas por página em um armazenamento de contexto SQLite temporário.
#817 (issue no GitHub)CorrigidoFuncionaManter problemas nativos em disco até que a agregação ordenada atribua suas identidades#817
de relatório.
#817 (issue no GitHub)CorrigidoFuncionaManter grupos nativos de duplicidade e de conteúdo em armazenamento SQLite ordenado#817
durante a análise.
#817 (issue no GitHub)AlteradoFuncionaLimitar buscas repetidas de páginas, agrupar a busca de backlinks dos problemas e…#817
Limita buscas repetidas de páginas, agrupa em lote a busca de backlinks dos problemas e resolve profundidades de descoberta nativa sem reconstruir todas as rotas nem carregar todos os nós no Python. Rotas longas mantêm sua profundidade exata e endpoints truncados explícitos.
#817 (issue no GitHub)AlteradoFuncionaTransmitir a entrada de páginas nativas retidas e as buscas de inlinks antes da#817
construção…
Deriva relações não vazias de corpus e de hreflang por meio de índices em disco, retém coleções completas de evidências no audit.v2 e rotula amostras limitadas de relações com suas contagens exatas de ocorrências.
#817 (issue no GitHub)AlteradoFuncionaLimitar o cache de páginas por bytes Python decodificados estimados, além da contagem…#817
Limita o cache de páginas pelos bytes Python decodificados estimados, além da contagem de entradas; páginas grandes sem cache continuam legíveis, e mutações invalidam seu peso antigo no cache. Mantém os rankings de tamanho HTML como pares escalares de URL e tamanho, estáveis, em vez de reter cada modelo completo de página, e evita reter JSON serializado de página em callbacks de mutação.
#817 (issue no GitHub)AlteradoFuncionaReter apenas fatos escalares de URL, status, indexabilidade, canonical e redirecionamento…#817
Retém apenas fatos escalares de URL, status, indexabilidade, canonical e redirecionamento ao verificar pares com e sem barra final, e fecha explicitamente as conexões SQLite do adaptador durável e do job remoto.
#817 (issue no GitHub)AlteradoFuncionaTransmitir contagens de cobertura de corpo indisponível e de charset, reter o estado…#817
Transmite as contagens de cobertura de corpo indisponível e de charset, retém o estado escalar de seleção da página de confiança em vez das populações candidatas de páginas, e processa as correspondências de DOM do HTML armazenado em duas passagens sobre o índice fixo de arquivos. Preserva a ordem do representante das variantes normalizadas, os exemplos de URL existentes, a cobertura completa das fontes correspondentes e cada problema.
#817 (issue no GitHub)AlteradoFuncionaValidar o JSONL legado de checkpoints de crawl linha a linha antes de anexar…#817
Valida o JSONL legado de checkpoints de crawl linha a linha antes de anexar, recusando evidências ausentes, corrompidas ou sem terminador, sem substituí-las. Compara checkpoints de formulários inline mais antigos com o seu sidecar, sem alocar uma segunda lista de formulários.
#817 (issue no GitHub)AdicionadoFuncionaAdicionar continuação de benchmark de JavaScript com proveniência verificada entre pares…#817
Adiciona continuação de benchmark de JavaScript com proveniência verificada entre pares concluídos, preservando recibos anteriores e orçamentos de disco. Casos interrompidos permanecem como bloqueios explícitos. Exige consulta e reanálise bem-sucedidas, além de evidência completa em CSV de páginas, antes de marcar um caso de benchmark como aprovado.
#817 (issue no GitHub)AlteradoFuncionaReter listas explícitas de URLs com o gravador SQLite nativo, preservando a ordem exata…#817
Retém listas explícitas de URLs com o gravador SQLite nativo, preservando a ordem exata de entrada, vários hosts e a semântica de modo sem descoberta. Transmite a entrada por arquivo de troca, preserva orçamentos de requisições e de tempo durante a retomada da coleta, retém evidências limitadas de resposta e de saltos, e mantém as verificações de grafo e de formulário explicitamente indisponíveis. Listas de diretórios grandes usam o mesmo spool, com uma ponte JSON de auditoria separadamente limitada.
#817 (issue no GitHub)AdicionadoFuncionaAdicionar companion SQLite audit.v2 versionado para coleções completas de auditoria além#816
do…
Adiciona um companion SQLite audit.v2 versionado para coleções ordenadas completas de auditoria além do limite de tamanho do JSON inline, com vinculação de proveniência do scan e validação de integridade de ponta a ponta.
#816 (issue no GitHub)AlteradoFuncionaTransmitir relatórios audit.v2 em JSON, CSV, XLSX, Markdown e DOCX, comparar populações…#816
Transmite relatórios audit.v2 em JSON, CSV, XLSX, Markdown e DOCX, compara populações de problemas de alta gravidade e mantém as operações de snapshot e prune pareadas com o companion, preservando o esquema scan.v1.
#816 (issue no GitHub)AlteradoFuncionaReter associações grandes de grupos ordenados uma única vez no audit.v2 revisão 3 e#816
ledger…
Retém associações grandes de grupos ordenados uma única vez no armazenamento audit.v2 (revisão 3) e no ledger (revisão 5), com leituras de audit compatíveis com versões anteriores, migração atômica do ledger, paginação explícita de membros via CLI e MCP, e companions BI de associações completas vinculados à origem.
#816 (issue no GitHub)AlteradoFuncionaPreservar o digest audit.v2 de origem na reanálise offline; persistir escopo incompleto…#816
Preserva o digest audit.v2 de origem durante a reanálise offline; persiste o escopo incompleto dos grupos do ledger e fecha os recursos de ingestão em caso de falha na validação.
#816 (issue no GitHub)AlteradoFuncionaReutilizar o resumo exato de capacidades do corpus enquanto um scan nativo somente…#815
Reutiliza o resumo exato de capacidades do corpus enquanto um scan nativo somente de metadados não tem evidências de resposta, documento, corpo ou recurso. Assim evita leituras repetidas de todo o corpus a cada commit de página esparsa, sem alterar o armazenamento do scan.
#815 (issue no GitHub)AdicionadoFuncionaAdiciona um perfilador offline e opcional de capacidade de varredura nativa, com links#815
dimensionados de forma independente, HTML retido e DOM renderizado, limites explícitos de recursos e um exercício de perda de processo e retomada. Ele reporta o limite existente de admissão de 50.000 URLs e a finalização incompleta como evidência bloqueada, e não como capacidade.
#815 (issue no GitHub)AlteradoFuncionaNomeia o cancelamento de requisição do navegador fixado como
render_cancellede fecha o#811contexto remoto isolado e o navegador em caso de cancelamento ou desconexão, sem fallback local.
#811 (issue no GitHub)AlteradoFuncionaPermite que a configuração remota confiável do projeto forneça referências de credenciais#810
de ambiente vinculadas ao host, com proveniência retida e redigida, e falha antes da coleta quando uma referência não estiver disponível.
#810 (issue no GitHub)AlteradoFuncionaPermite um transporte Playwright remoto, gerenciado pelo serviço e com verificação de#809
versão, para um projeto em fila, mantendo o endpoint fora dos envios e preservando as requisições de navegador fixadas e sujeitas à política.
#809 (issue no GitHub)AdicionadoFuncionaExpõe os caminhos observados, os inlinks reversos e o contexto de ocorrência das#807
varreduras salvas em uma única consulta somente leitura, limitada e compartilhada por CLI e MCP, com identidade explícita da varredura e resultados de erro.
#807 (issue no GitHub)AdicionadoFuncionaAdiciona posicionamento de links por ocorrência, limitado e somente leitura, e o contexto#806
do cabeçalho mais próximo, a partir do HTML estático retido e do DOM renderizado, preservando IDs de links duplicados e os estados explícitos de evidência indisponível ou parcial.
#806 (issue no GitHub)AdicionadoFuncionaNovo comando
semantic-inputs(seo_semantic_inputsvia MCP) gera o manifesto#801reproduzível de entradas normalizadas que o trabalho de similaridade semântica vai consumir: para cada documento, registra o hash do corpo retido, o hash exato da entrada decodificada, o hash da saída normalizada, a estratégia da área de conteúdo e a evidência de idioma (o próprio
#801 (issue no GitHub)<html lang>da página e as proporções de letras por script), nunca o texto normalizado em si.--scanfaz o streaming de corpos completos retidos, offline, com a configuração de área de conteúdo registrada no rastreamento e sem nova requisição; um corpo ausente ou parcial continua sendo uma omissão explícita, e não um resultado vazio limpo (#801).AlteradoFuncionaValida no PDF da auditoria técnica o número de páginas, o tamanho em bytes, o texto#800
extraível e a conservação dos registros…
Valida o número de páginas, o tamanho em bytes, o texto extraível e a conservação dos registros do modelo de origem do PDF da auditoria técnica antes que um relatório renderizado seja publicado.
#800 (issue no GitHub)AdicionadoFuncionaAdiciona saída bilíngue offline em PDF pelo Chromium aos caminhos compartilhados de build#799
de relatório, em CLI e MCP, validando e higienizando o arquivo temporário antes da substituição atômica.
#799 (issue no GitHub)AdicionadoFuncionaAdiciona layouts autocontidos de PDF de auditoria técnica em inglês e russo, com tokens#798
de marca neutros, gráficos de gravidade e cobertura, estados explícitos de execução incompleta e fluxo de páginas para conteúdo longo.
#798 (issue no GitHub)CorrigidoFuncionaMantém o layout do PDF separado da construção do modelo de auditoria e da integração com#798
CLI e MCP.
#798 (issue no GitHub)AdicionadoFuncionaAdiciona um modelo de conteúdo de PDF de auditoria técnica, versionado e offline, que#797
preserva registros de origem, contagens exatas de origem e projetadas, escopo e estados de cobertura para os dois contratos de auditoria suportados.
#797 (issue no GitHub)AlteradoFuncionaPersiste versões de cenários de workflow registrados, contexto do site e dos#796
concorrentes, evidência por etapa e portões de revisão. Execuções interrompidas podem ser retomadas por uma sessão local posterior, mas só depois que as dependências atuais continuarem válidas.
#796 (issue no GitHub)AlteradoFuncionaExige uma worklist do controlador para iniciar workflows e mantém recibos explícitos de#796
triagem de notas de especialistas para os resultados de tarefa, meta, concorrente, bloqueado ou rejeitado.
#796 (issue no GitHub)AlteradoFuncionaExige que os checkpoints de workflow bem-sucedidos verifiquem os bytes dos artefatos#796
retidos vinculados ao projeto contra seus recibos SHA-256. Evidência ausente ou alterada torna a conclusão anterior desatualizada, sem reescrever o histórico; os orçamentos de verificação nunca certificam evidência silenciosamente nem descartam o recibo dela.
#796 (issue no GitHub)AlteradoFuncionaPermite perfis explícitos e limitados de política de hash de evidência, normalizando#796
políticas antigas.
A observação passiva de workflow verifica os metadados de verificação retidos sem recalcular o hash dos artefatos; recibos alterados ou não verificados continuam explícitos.
#796 (issue no GitHub)AdicionadoFuncionaAdiciona o comando de CLI
project progress, limitado e paginado, e a ferramenta MCP#795
#795 (issue no GitHub)seo_project_progress, com contagens de estado do checklist e os próximos itens acionáveis. A visão reutiliza os resultados de cobertura no escopo e informa apenas um percentual de conclusão de tarefas de auditoria, explicitamente rotulado, quando cada site incluído tem um plano acordado e um denominador de tarefas medido e não vazio; a cobertura da população de URLs continua separada.AlteradoFuncionaOs checklists de projeto agora podem registrar o escopo de auditoria acordado e reportar#794
razões de cobertura honestas (#794).
#794 (issue no GitHub)project-checklist-init/seo_project_checklist_initaceitam umplanopcional: um revisor, umapopulationde URLs declarada comocomplete_set, umasamplenomeada ouunknown, com suasource,sizeouurlsenumeradas, além detemplatesopcionais com populações por template e um acordo opcional detasks(all_agreed, ou umaselectionde IDs de itens de checklist já existentes). Tudo isso fica vinculado à identidade do site do projeto e carimbado com a revisão de escrita. Registrar um plano atualiza o checklist paraseohead.coverage.v3e acrescenta ao histórico de planos retido; registrar de novo um acordo idêntico é uma operação sem efeito, e um acordo alterado marca as evidências anteriores como desatualizadas, em vez de reavaliá-las com um denominador modificado. Documentos v3 de plano único são migrados na leitura. Ler, reconciliar ou aplicar prioridades nunca atualiza nem inventa uma população, e documentos v1/v2 continuam carregando sem alterações. Itens fora de uma seleção são reportados comonot_agreed, visíveis fora de qualquer denominador.AlteradoFuncionaA conclusão do checklist agora segue o escopo medido: item automático no escopo do site,#794
apoiado por medição limitada…
A conclusão do checklist agora segue o escopo medido: um item automático no escopo do site, apoiado por uma medição limitada (scan parcial), continua pendente em vez de contar como concluído, enquanto um item com escopo em URLs de amostra explícitas ainda é concluído quando o artefato cobre exatamente esse escopo. O campo
#794 (issue no GitHub)completede nível superior agora significa que a auditoria no escopo foi concluída: todas as tarefas acordadas aplicáveis feitas, nenhuma exclusão pendente e a população de URLs acordada totalmente coberta por medições verificadas. Assim, um escopo desconhecido ou não medido nunca pode reportar uma auditoria concluída.AlteradoFuncionaO status do checklist agora retorna
coverage: cinco razões separadas,audit_tasks,#794checks…O status do checklist agora retorna
#794 (issue no GitHub)coverage, com cinco razões separadas:audit_tasks,checks(commeasured_urls),manual_review,deliverable_revieweurl_population. Cada uma tem seu própriobasis,numerator,denominatorestate, para que uma contagem de URLs nunca se misture com uma contagem de verificações ou de tarefas. Um denominador que não pode ser justificado ficanullcomstate: "unknown"e um motivo, em vez de virar 0/0 ou 100%. Medições que não podem ser verificadas contra a população acordada mantêm o eixo de URLs comopartiale contam apenas URLs elegíveis verificadas. A pertinência às URLs é verificada contra a enumeração acordada, então uma população declarada apenas porsizenão conta URLs medidas, e o numerador nunca pode exceder seu denominador. Populações por template são validadas como subpopulações acordadas da população do site quando um plano é registrado ou lido: URLs enumeradas de template devem pertencer ao conjunto de sites enumerado, e a pertinência declarada de template nunca pode exceder o tamanho acordado do site. Um plano incoerente é recusado, em vez de ser cortado ou contado além do denominador. As evidências de verificação salvas agora carregam a enumeração de URLs medidas, de modo que o numerador de URLs é um conjunto auditável, e não uma contagem de linhas. A agregação de vários sites soma os eixos por site e cai paraunknownsempre que um site não consegue justificar seu denominador.AlteradoFuncionaUm registro
not_applicableagora é uma exclusão revisada: exige motivo, revisor…#794Um registro
#794 (issue no GitHub)not_applicableagora é uma exclusão revisada: exige um motivo, um revisor e uma base de evidência inspecionável, seja umartifactcom hash vinculado ao projeto, seja uma referência explícita deevidence. Exclusões revisadas mantêm seu ID estável e seu histórico, saem dos denominadores de tarefas apenas por meio dessa decisão registrada e são listadas separadamente emexclusions. Um item desativado, um registro de exclusão desatualizado ou um registronot_applicablelegado, gravado antes da regra de base de evidência, permanece dentro do denominador comopending_exclusionaté ser revisado de novo. Assim, desativar, remover do catálogo ou reclassificar nunca reduz silenciosamente as contagens acordadas. Uma exclusão revisada nova em um item removido do catálogo é resolvida normalmente, em vez de ficar pendente para sempre.AdicionadoFuncionaAdiciona o prompt endereçável
workflow/full-audit-v1e o cenáriofull-auditpelas#793rotas de catálogo existentes…
Adiciona o prompt endereçável
#793 (issue no GitHub)workflow/full-audit-v1e o cenáriofull-auditpelas rotas de catálogo de skill e de cenário já existentes, em CLI e MCP. O workflow reutiliza os caminhos de coleta e de método já entregues, condiciona verificação e relatório à evidência real e separa a preparação do projeto da conclusão da auditoria completa.AlteradoFuncionaVincula decisões de remediação a artefatos de verificação imutáveis e a hashes exatos de#792
evidência antes e depois, incluindo as linhas de base audit.v2 em streaming.
#792 (issue no GitHub)AlteradoFuncionaReporta resultados de remediação retidos, com estados de cobertura representada e de#791
escopo completo, denominadores por tarefa e páginas de casos limitadas para ledgers grandes.
#791 (issue no GitHub)AdicionadoFuncionaAdiciona reverificações de remediação limitadas e indexadas pelo ledger, que reutilizam o#790
verificador protegido, fazem streaming de seleções audit.v2 e recusam desvio de escopo.
#790 (issue no GitHub)AlteradoFuncionaVincula a verificação de remediação à identidade da auditoria retida e à política#790
original que afeta os resultados. Um UUID de varredura reutilizado, sozinho, não consegue mais resolver um caso antigo.
#790 (issue no GitHub)AdicionadoFuncionaAdiciona o ledger de remediação
ledger.v1(seohead.storage.ledger, id de aplicação#788SEOL)…Adiciona o ledger de remediação
#788 (issue no GitHub)ledger.v1(seohead.storage.ledger, application idSEOL): um artefato SQLite separado e vinculado ao projeto, que registra achados, identidade por ocorrência, pertinência de URLs afetadas e histórico de observações somente de acréscimo, a partir de auditoriasscan.v1/scan.v2validadas, sem alterar as varreduras de origem. A ingestão vincula cada origem pelo UUID da varredura mais a revisão de evidência, o hash da auditoria e a identidade do produtor e da configuração. Reenvios exatos são idempotentes, e bytes conflitantes sob a mesma revisão são recusados de forma atômica. A coberturacapped/aggregate_onlye a evidênciaunavailablesão retidas como dados, e não tratadas silenciosamente como resolvidas. Inclui migração transacional 0→1, validação completa de schema e integridade na abertura, edocs/LEDGER.md(#788).AdicionadoFuncionaAdiciona um perfil descartável de proxy reverso TLS em loopback que verifica isolamento#787
autenticado de artefatos, backup e restauração, expiração e rollback atômico de upgrade, sem implantar nenhum serviço.
#787 (issue no GitHub)AlteradoFuncionaDocumenta jobs pontuais de CLI via SSH, registros de artefatos/incidentes, recuperação#787
sintética e o…
Documenta jobs pontuais de CLI via SSH, registros de artefatos e incidentes, recuperação sintética e o limite separado do futuro serviço: saúde, proxy, TLS e firewall.
#787 (issue no GitHub)AdicionadoFuncionaAdiciona o perfil de operador de serviço remoto self-hosted, com binds privados, saúde#787
autenticada…
Adiciona o perfil de operador de serviço remoto self-hosted, com binds privados, evidência de saúde autenticada, referências de arquivos de segredo, registros de incidentes, restauração consistente com SQLite, rollback de release e expiração explícita de artefatos terminais.
#787 (issue no GitHub)AdicionadoFuncionaAdiciona uma política de destino remoto vinculada ao projeto para jobs futuros em fila.#786
Quando vinculada por um worker, valida destinos e configurações, verifica o DNS novamente no despacho, fixa as requisições de recursos HTTP e de navegador e aplica orçamentos de requisições por origem e no total. Proxy remoto e backends alternativos de navegador falham de forma segura, ou seja, são bloqueados, até que a segurança do egress seja comprovada.
#786 (issue no GitHub)AdicionadoFuncionaAdiciona uma fila SQLite isolada por projeto e um worker de varredura nativa com lease#785
para a API remota autenticada e opcional. Os jobs retêm varreduras nativas e relatórios em JSON/Markdown, suportam envio idempotente, cancelamento, recuperação de falhas após reinício, downloads de artefatos com escopo e retenção explícita, sem habilitar nenhum listener por padrão.
#785 (issue no GitHub)AlteradoFuncionaDefine um contrato opcional, autenticado e versionado para a API de varredura remota, com#784
configurações nativas de rastreamento limitadas, permissões com escopo por projeto, envio idempotente, schema OpenAPI e evidência compatível com o status de varredura. Exige workers duráveis separados e política de destino e egress. Instalações locais de CLI/MCP permanecem inalteradas (#784).
#784 (issue no GitHub)AdicionadoFuncionaAdiciona um runbook SSH para Ubuntu com versão fixada e um smoke test descartável do#783
ciclo de vida Linux, que comprova instalação, renderização de JavaScript, descoberta de artefatos, upgrade, evidência de versão e rollback, sem serviço remoto.
#783 (issue no GitHub)AlteradoFuncionaNormaliza evidências de analytics e busca importadas para joins de varredura (#781).#781
#781 (issue no GitHub)evidence-normalizelê uma exportação CSV/XLSX/JSON fornecida, ou um envelope salvoseohead.provider-evidence.v1, totalmente offline, e produz um documento versionadoseohead.normalized-evidence.v1com base em um manifesto opcionalseohead.evidence-mapping.v1. Mantém a proveniência por campo (envelope, declarado ou desconhecido) para fonte, identidade do relatório, período, fuso horário, atribuição, mecanismo, cobertura de coleta e vínculo de URL. Um0medido continua zero, enquanto linhas ausentes, células nulas ou em branco, células de fórmula, valores suprimidos, períodos não coletados e coletas com falha ou ignoradas continuam explicitamente indisponíveis.evidence-joinune a evidência normalizada a uma lista de varredura, auditoria ou páginas, sob a política de chave estritaexternal_join.v1e apenas com relaxamentos explícitos. Ele preserva as populações com correspondência, só no rastreamento, só externas e não chaveáveis em sua granularidade declarada, e reporta colisões de chave em vez de multiplicar linhas.--comparecom uma política declarada acrescenta uma decisão pura de compatível, incompatível ou desconhecido sobre período, fronteira de fuso horário, identidade, atribuição, mecanismo e granularidade, e informa a elegibilidade de quadrantes com zero medido para o trabalho de coorte posterior. Fontes restritas mantêm linhas e identificadores dentro de um artefato local privado e retornam apenas contagens.AdicionadoFuncionaAdiciona uma experiência offline de prontidão de provedor, com referências de credencial#780
redigidas, schemas de rota de operação, metadados de cota e privacidade e estados explícitos de acesso ao alvo. A mera presença de credencial nunca verifica permissão.
#780 (issue no GitHub)AlteradoFuncionaExpande
seohead watchpara um observador de projeto somente leitura, com navegação de#775achados retidos, detalhe de evidências, estado de visões salvas e de revisão, e avisos de caixa de entrada MCP explicitamente restritos ao escopo.
#775 (issue no GitHub)AdicionadoFuncionaAdiciona entrega sintética autorizada de relatórios, com recibos de idempotência duráveis#773
e comportamento de reinício seguro para novas tentativas.
#773 (issue no GitHub)AlteradoFuncionaPreserva reivindicações de entrega incertas após a saída do processo ou confirmação#773
malformada de documento…
Preserva reivindicações de entrega incertas após a saída do processo ou uma confirmação malformada de documento, impedindo um segundo envio automático quando o aceite não puder ser estabelecido.
#773 (issue no GitHub)AlteradoFuncionaMede prévias de relatórios a partir da evidência retida, incluindo tamanho renderizado,#772
hash da fonte, contagens de população, cobertura e perfil. Reporta renderizadores ausentes e entradas acima do tamanho máximo antes do envio. Alinha o orçamento de JS do assistente completo ao contrato da fila compartilhada.
#772 (issue no GitHub)AlteradoFuncionaRetém identidades exatas de despacho confirmado do bot mesmo após falhas de fila e de#771
posse, deduplica atualizações confiáveis e isola status, cancelamento, recuperação e entrega por ator e chat iniciadores. Reexecuções idênticas e intencionais continuam sendo jobs separados.
#771 (issue no GitHub)CorrigidoFuncionaRestaura o último job confirmado do ator e chat após reinício do serviço, preservando#771
cancelamento…
Restaura o último job confirmado do ator e chat após o reinício do serviço, preservando o cancelamento e o comportamento de nova execução reconfirmada, sem retomar um rascunho não confirmado.
#771 (issue no GitHub)AdicionadoFuncionaAdiciona o pacote de evidências de revisão de software para autohospedagem, revisão#761
jurídica e de compras (#761).
#761 (issue no GitHub)scripts/generate_review_pack.pygera e verifica um inventário versionado de dependências e licenças (um perfil por grupo de instalação, com versões resolvidas e fontes de licença medidas no ambiente de geração; requisitos excluídos por marcador, não satisfeitos pela especificação ou não instalados são registrados, e não descartados), um documento de proveniência no nível da release, que vincula as distribuições construídas a uma tag e à revisão de origem do manifesto de build embutido, e umSHA256SUMS.txtque cobre tudo isso. A geração recusa uma tag que divirja depyproject.toml. A verificação revalida formatos e hashes registrados e reextrai cada distribuição para revalidar seu manifesto embutido, o nome e a versão declarados pelo nome do arquivo e os camposName/Versiondo próprio*.dist-info/METADATAouPKG-INFOcontrapyproject.toml, em vez de confiar no registro. Uma varredura de sentinelaSEOHEAD_REVIEW_CANARY_*comprova que os arquivos do pacote e os diagnósticos não carregam credencial plantada nem marcadores de cliente. A CI regenera e verifica o pacote com uma tag descartável em cada execução. O workflow de release o verifica e o anexa a uma releasev*real.AdicionadoFuncionaAdiciona
docs/SOFTWARE_REVIEW.md: o mapa de endpoints de saída e de fluxo de dados (o#761que cada recurso contata, o que envia e se a chamada é opcional), a fronteira local e remota, o armazenamento de credenciais e artefatos, o status de telemetria, a forma de reportar problemas de segurança e o status de manutenção, e como revisar mudanças de release. Ele linka os runbooks de instalação e implantação em vez de duplicá-los (#783, #787).
#761 (issue no GitHub)AdicionadoFuncionaAdiciona uma verificação prévia offline de capacidade e checksum do Google Sheets para#760
pacotes BI locais completos. Não faz nenhuma requisição ao Google nem gravação em planilha.
#760 (issue no GitHub)AdicionadoFuncionaAdiciona um transporte explícito de substituição do Google Sheets, com lista de#760
permissões e mapeamentos de aba por dataset…
Adiciona um transporte explícito de substituição do Google Sheets, com lista de permissões, mapeamentos de aba por dataset, staging e leitura de verificação limitados e uma única publicação atômica apenas de valores, que preserva os IDs de aba existentes.
#760 (issue no GitHub)AlteradoFuncionaRegistra o staging do Google Sheets antes de qualquer criação remota de stage e#760
reconcilia uma resposta perdida…
Registra o staging do Google Sheets antes de qualquer criação remota de stage e reconcilia uma resposta de início perdida pelas identidades determinísticas das planilhas de stage antes de tentar novamente.
#760 (issue no GitHub)AlteradoFuncionaPreserva valores numéricos e booleanos tipados e leituras esparsas do Google, rejeita#760
alvos de aba duplicados e divergência de contrato de dataset, vincula a recuperação ao alvo exato configurado e retém o staging retomável após esgotamento de cota. Orça o crescimento da grade de destino antes da substituição atômica e reporta contagens de linhas não confirmadas em execuções interrompidas.
#760 (issue no GitHub)AlteradoFuncionaValida companions de grupo completos e vinculados à origem antes de gravações no destino…#760
Valida companions de grupo completos e vinculados à origem antes de qualquer gravação no destino, preserva-os junto com os achados selecionados e divulga referências de pertinência apenas locais nos recibos do destino e da pasta de trabalho, sem afirmar que o companion foi enviado.
#760 (issue no GitHub)AlteradoFuncionaDivide grandes conjuntos de registros XLSX do
scan-exportem abas numeradas e#759determinísticas, com uma aba Partitions de conservação de linhas, em vez de falhar no limite de linhas por aba do Excel.
#759 (issue no GitHub)AlteradoFuncionaDivide as abas Findings e Pages do
report-buildno limite de linhas do Excel e emite um#759.xlsx.index.json…
Divide as abas Findings e Pages do
#759 (issue no GitHub)report-buildno limite de linhas do Excel e emite um.xlsx.index.jsoncom hash, com intervalos exatos de registros, população de origem, referências de seleção e cobertura. Preserva o relatório anterior quando falhas de gravação são capturadas e limpa os spools de streaming em caso de interrupção.AlteradoFuncionaRecusa células XLSX acima de 32.767 caracteres antes que a biblioteca de planilhas possa#759
truncá-las, protege os metadados da aba Summary contra injeção de fórmulas e rejeita linhas de auditoria retidas malformadas antes que uma exportação incompleta possa declarar sucesso. CSV e JSON completos e a política limitada de visão geral em PDF continuam disponíveis.
#759 (issue no GitHub)AdicionadoFuncionaAdiciona entrega limitada de CSV para BI selecionado, com contabilização exata de linhas#759
de origem, selecionadas e omitidas…
Adiciona entrega limitada de CSV selecionado para BI, com contabilização exata de linhas de origem, selecionadas e omitidas, cobertura de origem retida, hashes em streaming e um índice durável de intervalos de CSV para aba XLSX. Células grandes do Excel falham antes de serem truncadas, e a saída interrompida não é marcada como concluída.
#759 (issue no GitHub)AlteradoFuncionaPreserva linhas completas e imutáveis de cobertura de verificações ao lado das#759
exportações BI de achados selecionados, incluindo os motivos de verificações ignoradas, e oferece suporte à seleção exata de achados por segmento de escopo de rastreamento retido.
#759 (issue no GitHub)AdicionadoFuncionaAdiciona diagnósticos offline de rastreamento para varreduras nativas salvas e artefatos#758
legados de execução, com evidência de decisão limitada, explicações acionáveis, acesso somente leitura via CLI e MCP e um comando e ferramenta separados de exportação redigida e opt-in.
#758 (issue no GitHub)AdicionadoFuncionaAdiciona visões de achados de projeto versionadas, com filtros fechados e ordenação#757
sensível à gravidade…
Adiciona visões de achados de projeto versionadas, com filtros fechados, ordenação sensível à gravidade, projeção de colunas e paginação limitada. Ordenar por gravidade decrescente coloca os achados críticos primeiro; em ordem crescente, a lista vai de aviso até crítico. CLI, MCP, relatórios e a futura navegação no terminal podem reutilizar a mesma visão somente leitura, sem alterar a evidência de origem, a pontuação, as tarefas ou a cobertura.
#757 (issue no GitHub)AdicionadoFuncionaAdiciona planejamento de monitor local, desativado por padrão, com orçamentos explícitos#756
de atualização incremental e completa, recusa de sobreposição, reivindicações de recuperação, proveniência imutável das observações, retenção de resultados parciais, alertas deduplicados e avisos de recuperação. O monitor não inicia nenhum timer, rastreamento nem canal de entrega.
#756 (issue no GitHub)AdicionadoFuncionaAdiciona um adaptador de entrega de serviço injetado e explícito para avisos completos de#756
monitor retidos.
Exige um destino autorizado e vinculado ao projeto e um armazenamento durável de recibos. Nenhum transporte, conta, timer ou destino é habilitado por padrão.
#756 (issue no GitHub)AlteradoFuncionaTorna reivindicações de monitoramento retidas, cobertura, proveniência de cache,#756
evidência de recuperação derivada e entrega opcional de serviço seguras para reinício.
#756 (issue no GitHub)AdicionadoFuncionaAdiciona um coletor de monitor pontual, explícito e limitado por lease, com evidência#756
retida consciente de cache e recibos de entrega somente locais.
#756 (issue no GitHub)AdicionadoFuncionaAdicionado
verify-fixes/seo_verify_fixespara reverificar URLs selecionadas a#755partir de IDs de achados salvos…
Adicionado
#755 (issue no GitHub)verify-fixes/seo_verify_fixespara reverificações limitadas de URLs selecionadas, a partir de IDs de achados salvos, de uma visão de verificação ou de uma lista explícita de URLs. A ferramenta reaproveita a política de rastreamento registrada, grava um artefato de verificação separado (sem sobrescrever nada) e um relatório focado, e distingue achados resolvidos, persistentes, alterados e não verificáveis. Uma auditoria “after” existente só pode ser verificada sem acesso à rede quando tiver um UUID de scan próprio e um horário de observação registrado posterior; evidências não medidas ou de todo o site nunca são marcadas como corrigidas.AlteradoFuncionaRastreamentos nativos de URL podem filtrar rotas descobertas pela extensão final do#749
arquivo antes…
Rastreamentos nativos de URL podem filtrar rotas descobertas pela extensão final do nome do arquivo antes das requisições, e pelo
#749 (issue no GitHub)Content-Typereal da resposta antes do parsing ou da retenção do corpo. As duas etapas de filtro registram suas decisões e preservam as evidências de links, status, cabeçalhos e redirecionamentos; os metadados de HTML filtrados continuam explicitamente não medidos. Recursos de script e folha de estilo mantêm seleção e orçamento de bytes independentes.AlteradoFuncionaQuando o corpo HTML não está disponível, os achados derivados dele agora mantêm cobertura#749
explícita como ignorada, em vez de tratar os padrões do parser como limpos ou como metadados ausentes observados.
#749 (issue no GitHub)AdicionadoFuncionaAdiciona exclusões auditáveis, por padrão de URL e aplicadas após a análise, para os#748
achados.
Achados suprimidos continuam no JSON da auditoria e nas exportações do report-build, com a regra correspondente e o motivo, enquanto os totais de achados ativos, a pontuação e o backlog de tarefas refletem a política configurada. Os artefatos de scan nativos preservam a política para reanálise offline; a quantidade de regras e o tamanho dos campos são limitados.
#748 (issue no GitHub)AdicionadoFuncionaAdiciona
scan-export(seo_scan_export): uma exportação somente leitura e offline dos#747dados de scan, sob o contrato versionado
#747 (issue no GitHub)scan_export.v1. Ela lê um artefato SQLitescan.v1validado ou umaudit.jsondo SF Analyzer e grava CSV (um arquivo por tipo de registro, mais um manifesto), XLSX (pasta de trabalho somente de escrita), um envelope JSON em streaming ou um documento XML documentado. Cada saída traz proveniência, contagens de linhas exportadas, estatísticas da execução e cobertura explícita — incluindo quais verificações rodaram, foram ignoradas, estavam desativadas ou ficaram sem contabilização —, nada disso podendo ser removido pela seleção de campos.--recordse--fieldsoferecem projeção validada entre registros de páginas, links e achados; tipos de registro ou nomes de campo desconhecidos são rejeitados antes de qualquer arquivo de saída ser criado. Valores ausentes permanecem explícitos (nullno JSON,state="absent"no XML,\Nno CSV/XLSX), em vez de virar zeros fabricados. A saída XML é serialização gerada, com escape UTF-8 correto; ela nunca interpreta XML, DTDs, folhas de estilo ou entidades fornecidas pelo usuário. CSV/XLSX mantêm a defesa existente contra injeção de fórmulas; o XLSX recusa estouros de linha, coluna e texto de célula do Excel em vez de truncar, e qualquer falha de serialização não deixa nenhum artefato parcial plausível.AlteradoFunciona
crawl-siteganha verificação opcional e limitada dos destinos externos registrados:#746
#746 (issue no GitHub)discovery.external.crawlexecuta uma fase separada depois que a fronteira interna fecha, buscando cada destino de link de saída distinto uma única vez, com orçamentos próprios deexternal_checks.max_targets/max_hosts/max_requests/max_depth/max_redirects— nunca um percurso recursivo para fora do host. Os resultados (buscado, falhou, bloqueado, ignorado com a regra que recusou) são anexados aexternal_checks.jsonlno diretório da execução, mantêm a proveniência da página de origem, persistem ao retomar sem reabrir orçamentos já gastos e informam sua cobertura emdiscovery.external_checks, separada da completude do rastreamento interno. Exigediscovery.external.store; é recusado pelo nome na rota SQLite nativa (--scan-out) até que esse coletor ganhe a fase.AdicionadoFuncionaAdiciona política explícita e validada de proxy HTTP para o rastreamento nativo em#745
páginas…
Adiciona uma política explícita e validada de proxy HTTP de encaminhamento para o rastreamento nativo, nas requisições de página, sitemap, recursos e navegador fixado, com proveniência de rota redigida.
#745 (issue no GitHub)AlteradoFuncionaA etapa de renderização do rastreador nativo agora expõe o navegador pela configuração…#744
A etapa de renderização do rastreador nativo agora expõe seu navegador pela configuração, em vez de fixar o Chromium:
#744 (issue no GitHub)rendering.browser.engineselecionachromium(ainda o padrão),firefoxouwebkitpelo mesmo caminho protegido do Playwright; um nome desconhecido falha na validação das configurações, e não no lançamento; e um motor solicitado cujo binário não está instalado gera um erro de dependência que indica a correção (playwright install <engine>), em vez de cair silenciosamente no Chromium. A limitação documentada do Firefox é aplicada com honestidade: ele rejeitarendering.browser.mobile_emulation(is_mobilenão é suportado ali), enquantorendering.browser.touch_emulation(has_touch), que é independente, ainda chega ao contexto. Sondagens e renderizações completas compartilham uma única configuração efetiva, então um padrão nunca é escalado por um navegador diferente daquele que produziu a evidência.AlteradoFunciona
rendering.browser.viewport_widtherendering.browser.viewport_heightadicionam#744dimensões arbitrárias de viewport ao lado das predefinições
#744 (issue no GitHub)desktop/mobile, que continuam definindo o perfil exatamente como antes. O par é tudo ou nada e limitado a 1..16384 px; um par personalizado substitui apenas as dimensões da predefinição — não implica emulação de mobile ou de toque, que continuam sendo flags explícitas definidas pelo operador.AlteradoFunciona
rendering.browser.page_concurrencylimita quantas buscas no navegador podem estar em#744andamento durante a escalada, separadamente de
#744 (issue no GitHub)speed.concurrency, que continua regulando a cortesia do rastreamento HTTP. O padrão 1 preserva o comportamento sequencial e não cria pool algum; acima de 1, sondagens e renderizações rodam em um pool de workers limitado, enquanto todo veredito, commit e escrita no SQLite permanecem na thread orquestradora, na ordem de submissão. O prazo de renderização, o orçamento de URLs e as políticas amostrada/completa valem mesmo com concorrência; um lote interrompido aguarda as páginas que já começou e nunca agenda novas; e workers interrompidos ou com falha não deixam thread, página, contexto ou navegador ativos após a chamada.AlteradoFuncionaO motor selecionado, sua versão realmente informada, o viewport efetivo e a concorrência#744
de páginas configurada são registrados no manifesto e na impressão digital do rastreamento, e na proveniência do renderizador de cada documento renderizado — inclusive em tentativas que falharam, que registram o que foi solicitado sem inventar uma renderização bem-sucedida. Os dois caminhos de escalada respeitam as configurações: o rastreamento de diretório e o scan nativo em SQLite, em que os candidatos a links renderizados entram na fronteira pela admissão já existente, com deduplicação, quando
#744 (issue no GitHub)rendering.rendered_links.crawlestá habilitado.AdicionadoFuncionaAdiciona verificações opcionais de canonical para padrões de paginação e filtro na#727
auditoria…
Adiciona verificações opcionais da política de canonical para padrões configurados de paginação e filtro nos pipelines de auditoria da exportação SF e do rastreamento nativo. Regras de paginação aceitam destinos self, primeira página ou landing; regras de filtro aceitam destinos self ou landing. Políticas ausentes e destinos que não aparecem na evidência do rastreamento continuam não medidos, e as verificações de status de resposta do destino permanecem separadas.
#727 (issue no GitHub)AdicionadoFuncionaAdiciona arquivos retomáveis de Search Analytics do GSC no histórico SQLite local#718
compartilhado…
Adiciona arquivos retomáveis de Search Analytics do GSC no armazenamento SQLite local compartilhado de histórico de provedores, expostos de forma consistente por
#718 (issue no GitHub)gsc-archiveeseo_gsc_archive. Status offline, preparação explícita, coleta limitada e snapshots verificados compartilham um único núcleo.AlteradoFuncionaPreserva a proveniência de provedor/motor e métricas anuláveis, enfileira só intervalos…#718
Preserva a proveniência de provedor/motor e métricas anuláveis, enfileira apenas os intervalos de disponibilidade ainda não cobertos e registra esperas por cota e novas tentativas limitadas em falhas transitórias.
#718 (issue no GitHub)AdicionadoFuncionaAdiciona um histórico SQLite local e versionado para GA4, Metrika, consulta/página do GSC#716
na web…
Adiciona um único histórico SQLite local e versionado para GA4, Metrika, consulta/página da web no GSC e dados diários do Yandex Webmaster, com substituição atômica de dias e cobertura explícita: solicitado, vazio, parcial, com falha e atrasado.
#716 (issue no GitHub)AdicionadoFuncionaExpõe sincronização determinística e limitada, status offline e exportação JSON/CSV pela#716
CLI compartilhada e pelo MCP local, incluindo aditividade de métricas e metadados conservadores de fuso horário. Nenhuma credencial ou dado de provedor é armazenado no repositório.
#716 (issue no GitHub)AlteradoFuncionaO modo A do SF agora verifica os recursos de exportação solicitados pela CLI instalada e#715
exige um conjunto completo e recente de exportações antes da análise. A proveniência do perfil completo registra o manifesto de exportação verificado e a leitura da taxa de rastreamento; um limite de taxa explícito falha antes do rastreamento quando sua configuração base está ausente ou é inválida.
#715 (issue no GitHub)AlteradoFunciona
metrika-report(seo_metrika_report) eMetrikaClient.report(): uma recusa da#714Reporting API com “Query is too complicated” agora é repetida em fatias por mês-calendário, com backoff de 5–15 s; uma fatia que ainda for recusada é reenviada com
#714 (issue no GitHub)accuracy=0.1amostrado. Somente métricas comprovadamente aditivas em períodos disjuntos (ym:s:visits,ym:s:pageviews) são mescladas — uma consulta de visitantes únicos, percentuais, médias ou métricas não verificáveis é recusada antes da primeira requisição de fatia, em vez de devolver um valor somado que estaria errado. As fatias são mescladas à medida que chegam, sob um único limite global de linhas que também limita os downloads: quando o limite se esgota, as partições restantes nunca são solicitadas e seus intervalos de datas são listados emsplit.unfetched— uma fatia interrompida no meio lista o próprio intervalo ali, compartial—;total_rows/totalsdo período inteiro permanecem desconhecidos quando os períodos não consultados os tornam impossíveis de saber, e a janela devolvida é marcada como parcial. Respostas mescladas reaplicam osortdo chamador (dimensões e métricas, ou o padrão da API, a primeira métrica em ordem decrescente), e a janelaoffset/limité tirada do conjunto global mesclado. Os campos de amostragem refletem o que a API realmente informou (sampled, piorsample_share), e uma fatia que não os informa deixa o valor do período inteiro desconhecido —nullna resposta da CLI/MCP, nunca umfalseinventado.contains_sensitive_dataé o OR entre as fatias;min/maxsão recalculados sobre as linhas mescladas; células de métrica e totais ausentes ou malformados marcam o corpo comoincomplete, em vez de lerem como zero. O blocosplitmantém os períodos solicitados e resolvidos, o fuso horário usado e, por fatia, accuracy, tentativas, linhas descartadas e metadados de amostragem; uma partição que falha nomeia os intervalos concluídos e as accuracies esgotadas. Datas relativas (today,NdaysAgo) são resolvidas notimezoneda requisição ou no fuso do próprio contador (time_zone_name, senão seu deslocamento em minutos) — nunca na data do host. Um período que não pode ser mapeado para datas (um atalho comomonth) ainda é repetido e amostrado antes de o erro ser relançado. Umaccuracyexplícito é respeitado em todas as formas documentadas (low/medium/high/fullou uma fração numérica como"1"): qualquer valor acima da amostra de último recurso mantém o fallbackaccuracy=0.1, enquanto uma configuração já mais baixa do chamador (lowou uma fração igual ou abaixo dela) é preservada, em vez de ser reamostrada para cima. Toda requisição tentada — inclusive a chamada recusada do intervalo inteiro — chega ao diário de gastos.AlteradoFuncionaYandex Webmaster: a operação
indexingagora lê o endpoint v4 real/indexing/samples,#713em vez do inexistente
#713 (issue no GitHub)/search-urls; o novobroken_links_sampleslê/links/internal/broken/samples; e a paginação respeita o limite documentado de cada endpoint por página (500 para consultas, 100 para as listas de amostras), em vez de enviarlimit=500em todos os casos (#713).AlteradoFuncionaA coleta paginada do Yandex Webmaster agora valida o
countdocumentado de cada página e#713o formato da lista — inclusive um
#713 (issue no GitHub)countmenor que o número de linhas devolvidas —, pede por página no máximo o restante do orçamento de linhas, para que um corte pormax_rowsnunca leia além e gere um falsocomplete; expõereturned/truncatedpara uma única página não paginada, como fatia limitada; informapartialsempre que restarem linhas não lidas; e falha em páginas malformadas, em vez de declarar um resultado vazio como completo (#713).AlteradoFuncionaA verificação de renderização agora usa a confiança da plataforma mais uma CA#709
explicitamente selecionada, reproduz subrequisições POST fixadas e informa falhas de verificação de certificado sem detalhes de transporte.
#709 (issue no GitHub)AlteradoFuncionaReconhece a falha de verificação TLS do transporte de proxy fixado e verifica a confiança#709
explícita em CA de fixture, a reprodução de POST, os limites de resposta e a rejeição de alvos privados, por meio de um interceptor CONNECT sintético e próprio, sem alterar a confiança da plataforma.
#709 (issue no GitHub)
3 de outubro de 2026
5 adicionado8 alterado1 corrigidoAdicionadoFuncionaAdiciona
crawl-importpara pacotes CSV de rastreamento de terceiros com mapeamento#819explícito, preservando a identidade da fonte externa, a cobertura por campo, observações duplicadas e dados indisponíveis em
#819 (issue no GitHub)third_party_crawl.v1, sem tratar o resultado como um scan nativo nem como uma auditoria SF.AdicionadoFuncionaAdiciona um transporte opcional de navegador Playwright remoto com verificação explícita…#808
Adiciona um transporte opcional de navegador Playwright remoto, com verificação explícita de endpoint e de versão, estados de falha seguros e nenhum fallback para execução local, preservando os padrões de renderização local.
#808 (issue no GitHub)AdicionadoFuncionaAdiciona consultas Python somente leitura, limitadas e determinísticas, de menor caminho#805
observado e de inlinks reversos sobre os links retidos no scan, com identidade do registro de scan em cada salto e cobertura explícita de grafo parcial.
#805 (issue no GitHub)AlteradoFuncionaAlinha a regressão de roteamento de provedores ao contrato corrigido do Arsenkin Wordstat#779
Alinha a regressão de roteamento de provedores ao contrato corrigido da requisição de frequência do Arsenkin Wordstat (#720, #779).
#779 (issue no GitHub)AdicionadoFuncionaAdiciona
docs/PROVIDERS.md, uma matriz gerada de capacidades de provedores e workflows…#779Adiciona
#779 (issue no GitHub)docs/PROVIDERS.md, uma matriz gerada de capacidades de provedores e de workflows especialistas (#779, épico #753). Renderizada a partir do registro ao vivo de provedores, somado a um catálogo curado de workflows emseohead/core/provider_matrix.py, viascripts/generate_provider_matrix.py, ela registra, por workflow, os comandos entregues, autenticação, custo/cota, classe de privacidade, limitações e o fallback em CSV por meio deprovider-join. Os status distinguem suportado, parcial, não suportado e não verificado; nenhum provedor declarado é rotulado como verificado ao vivo, trabalhos explicitamente não suportados são listados pelo nome, e uma primeira versão em fases é selecionada sem afirmar que todos os serviços estão cobertos. O desvio entre o documento commitado e os registros é detectado portests/test_docs_drift.pyetests/test_provider_matrix.py.CorrigidoFuncionaCorrige
keywords-exact/seo_keywords_exact, que nunca conseguia devolver resultado:#720a tarefa era criada para uma ferramenta do Arsenkin chamada
#720 (issue no GitHub)keywords_frequency, que não existe, então toda chamada respondia404 WRONG_TOOL. O!Wexato agora vai para a ferramentawordstatcomtype=1, o array de frases emqueriese a região como lista de um único item.AlteradoFuncionaSolicita o seletor
overalpara!W: os valoreswsdo Arsenkin são operadores#720distintos —
#720 (issue no GitHub)baseé amplo (WS),quotedé a frase entre aspas (“WS”),overalé a forma exata da palavra (!WS), que é o que!Wpede, eexacté a forma de ordem estrita ([!WS]).AlteradoFuncionaRemove a pontuação que o provedor recusa antes do envio: uma frase com
/ou aspas…#720Remove a pontuação que o provedor recusa antes do envio: uma única frase contendo
#720 (issue no GitHub)/ou aspas fazia o provedor rejeitar o lote inteiro com422 JSON_VALIDATION_ERROR. As frases reescritas são informadas emcleaned, para que quem chama veja quais foram medidas em outra forma.AlteradoFuncionaDevolve
frequenciescomo{phrase: {"base": N, "overal": N}}junto ao payload bruto do#720provedor. Uma frase cujo resultado cita apenas outras regiões é omitida e listada em
#720 (issue no GitHub)warnings, em vez de pegar emprestados os números de outra região.AdicionadoFuncionaAdiciona acesso somente leitura e limitado ao Topvisor pela CLI e pelo handler MCP#719
compartilhados, com arquivos centrais de credenciais, paginação explícita e nenhuma operação de verificação paga.
#719 (issue no GitHub)AlteradoFuncionaAlinha o bloco legado
sources.gscdosources-doctorcomprovider_status.gsc:#717
#717 (issue no GitHub)readye o novo campocomponentspassam a vir dos mesmos componentes de credencial (bearer OAuth, concessão durável ou conta de serviço), em vez de apenas do arquivo bearer; assim, uma conta de serviço configurada deixa de aparecer como se o GSC não estivesse configurado. O componente de conta de serviço agora valida o próprio documento JSON (arquivo regular privado, tamanho limitado, tiposervice_account, a URI exata de token do Google e os campos obrigatórios), e os dois blocos do doctor informam um enum seguroservice_account_status(missing,unsafe_file,too_large,unreadable,malformed_json,unsupported_shapeouconfigured_unverified). Assim, um arquivo grande demais, ilegível ou malformado continua distinguível de um arquivo configurado mas não verificado, sem expor seu conteúdo.AlteradoFuncionaOs artefatos de scan do
crawl-siteagora registramfinished_ate um ciclofinished…#712Os artefatos de scan do
#712 (issue no GitHub)crawl-siteagora registramfinished_ate um ciclo de vidafinishedassim que cada linha aceita da fronteira atinge um estado terminal, inclusive em execuções cuja evidência retida é parcial:crawl_partialjá informa observações omitidas, então uma fila esvaziada não aparece mais como captura interrompida emscan-status,scan-listou no histórico (#712). Uma execução explicitamente interrompida — abortada antes de aceitar trabalho, cancelada ou parada pelo circuito de erros — mantéminterruptede o motivo registrado, mesmo depois que a fila esvazia, inclusive viaresume_or_finalize; assim, os caminhos de parada nunca recebem um carimbo de finalização falso.AlteradoFunciona
duplicate-check --scaneboilerplate-report --scanagora processam em streaming um#710corpus retido, em vez de falhar em sites de tamanho normal: o prazo de abrir e validar o scan é calculado pelo tamanho do artefato, e cada leitura de documento tem prazo próprio; assim, um corpus de 1.500 páginas não termina mais em
#710 (issue no GitHub)interrupted. O orçamento de bytes de entrada do corpus mede o que o analisador realmente retém — Markdown extraído para duplicatas e um digest por página para boilerplate — e não o tamanho bruto do HTML. Ao atingir um limite do corpus, a cobertura é informada como parcial, com as contagens exatas de preparados e elegíveis e o limite que interrompeu a leitura (#710).AlteradoFunciona
report()eby_time()do Metrika agora rejeitamoffset < 1localmente com#707ValueError…
#707 (issue no GitHub)report()eby_time()do Metrika agora rejeitamoffset < 1localmente, com umValueError, em vez de repassá-lo à Reporting API, que respondeoffset=0com HTTP 400. Novos testes offline fixam o contrato com base 1 emmetrika-report,seo_metrika_reporteaggregate_reportdoprovider-collect, e verificam que as condições de parada paginadas (total_rows,ROW_CAP) contam as linhas puladas antes de umoffsetdiferente do padrão (#707).
2 de outubro de 2026
1 adicionado2 alteradoAlteradoFunciona
metrika-traffic-pdfno macOS: o Chrome grava o PDF e continua rodando; o navegador é…#731
#731 (issue no GitHub)metrika-traffic-pdfno macOS: o Chrome grava o PDF e continua rodando; o navegador agora é iniciado sem esperar e encerrado assim que o PDF é verificado.AlteradoFuncionaYandex Webmaster: o
user_idé resolvido a partir do token; novas operações somente#713leitura
#713 (issue no GitHub)summary,diagnostics,sqi_history,search_history,query_history,in_search_history,events_history,indexing_history,important_urls,broken_links_history,external_links_history;paramspara datas e indicadores; paginação das listas de consultas e de amostras de rastreamento (#713).AdicionadoFuncionaNova skill técnica
traffic-report: um relatório mensal ou anual de tráfego para ocliente…
Nova skill técnica
traffic-report: um relatório mensal ou anual para o cliente, a partir do Metrika, do Webmaster e do Search Console (conversões contadas como visitas, verificações de sanidade das metas, produtos, perfil do comprador e regras de slides).
1 de outubro de 2026
1 adicionado1 alteradoAdicionadoFuncionaAdiciona
metrika-traffic-pdf(seo_metrika_traffic_pdf): um relatório estático de#731tráfego em A4 paisagem, no layout de um dashboard analítico, gerado a partir do Yandex Metrika. Coleta e renderização são etapas separadas. A coleta lê a Reporting API (cerca de 40 requisições gratuitas e somente leitura) e produz um único documento
#731 (issue no GitHub)seohead.metrika-traffic/1: nove cartões de KPI (usuários, visitas, visualizações de página, páginas por visita, visitas por dia, taxa de rejeição, duração média da visita, parcela de visitantes com duas ou três visitas e parcela de novos visitantes), com variações em relação ao período anterior de mesma duração e às mesmas datas um ano antes; dinâmica diária; janelas de 3, 6 e 12 meses comparadas às janelas anteriores; buscadores, cidades, países, dispositivos, idade, gênero, principais páginas de entrada e frases de busca; e todos os canais de tráfego. A renderização converte esse documento em HTML autocontido, com gráficos SVG inline, e o imprime em PDF por meio de um Chrome, Edge ou Chromium instalado localmente (SEOHEAD_CHROMEsobrescreve a descoberta). Marca (nome, cores, pilha de fontes, texto do logotipo) e rótulos em inglês ou russo são entradas; linhas de consultas do Search Console podem ser adicionadas como página opcional. A atribuição usa por padrão a última fonte significativa (ym:s:lastSignTrafficSourcee suas dimensões de buscador e frase), que é o que a interface do Metrika informa; as dimensões de último clique diferem dela em alguns por cento e continuam disponíveis comoattribution=last_clickexplícito. Toda requisição enviaoffset=1, porque a API conta as linhas a partir de 1. Dados ausentes ficam visíveis: cada bloco trazok,unavailableouskippedcom motivo; uma variação sem linha de base énull, não zero; um navegador ausente deixa o HTML e marca o PDF como ignorado; e arquivos existentes emout_dirsó são substituídos comoverwrite=true.AlteradoFuncionaRelatórios do Metrika começam em
offset=1: a Reporting API é baseada em 1 e respondia#707com HTTP 400 a todas as requisições enviadas com
#707 (issue no GitHub)offset=0(#707, #728, #729).
26 de setembro de 2026
1 adicionadoAdicionadoFuncionaAdiciona evidência
HEADING_SKIPno rastreamento nativo para saltos de nível em H1–H6…#725Adiciona evidência
#725 (issue no GitHub)HEADING_SKIPno rastreamento nativo para saltos de nível de H1–H6 na região de conteúdo nomeada. Títulos de cabeçalho, rodapé, navegação, barra lateral e títulos explicitamente ocultos ou em diálogos fechados são excluídos, para que a interface do template não crie uma hierarquia falsa; execuções somente com exportação do Screaming Frog informam a verificação como indisponível.
23 de setembro de 2026
1 alteradoAlteradoFuncionaAceita arquivos de segredo privados no Windows, onde não existem bits de permissão POSIX,#708
e adiciona um script de consentimento no navegador que armazena uma concessão somente leitura do Search Console.
#708 (issue no GitHub)
13 de setembro de 2026
2 adicionado3 alterado2 corrigidoAdicionadoFuncionaSuporta gravadores SQLite nativos, histórico, retentativa, snapshots, reanálise e#705
publicação de projetos no Windows, com travas por intervalo de bytes gerenciadas pelo sistema operacional e verificações portáteis de espaço livre. Preserva o flush de diretório em POSIX; o flush de arquivo no Windows e a publicação atômica continuam disponíveis, sem a garantia de fsync de diretório POSIX. Os fluxos portáteis são testados no CI do Windows e em um runtime Linux isolado.
#705 (issue no GitHub)CorrigidoFuncionaMantém a varredura de HTML em texto bruto compatível com versões do Python sem a opção…#705
Mantém a varredura de HTML em texto bruto compatível com versões do Python que não têm a opção de scripting mais recente do HTMLParser, inclusive a distribuição do Python 3.12 para Windows.
#705 (issue no GitHub)CorrigidoFuncionaCorrige e cita a orientação do Google sobre dados estruturados e Googlebot, incluindo#704
FAQ/HowTo…
Corrige e cita a orientação do Google sobre dados estruturados e Googlebot, incluindo a disponibilidade de FAQ/HowTo e as consequências da política de dados estruturados.
#704 (issue no GitHub)AlteradoFuncionaDescobre sitemaps a partir da raiz do site pelo
robots.txt, com fallback para#703
#703 (issue no GitHub)/sitemap.xml, e informa a expansão de sitemap que falhou por completo comook: false.AlteradoFuncionaPermite retomar o rastreamento nativo após cookies anônimos definidos pelo servidor e#702
registra a nova sessão sem reter os valores dos cookies; rastreamentos com credenciais ou perfil persistente continuam não retomáveis.
#702 (issue no GitHub)AlteradoFuncionaPadroniza os caminhos de scan salvos como
--scane o JSON inline como--input; o#701
#701 (issue no GitHub)--inputcom caminho de scan e o--json-inputlegados continuam funcionando por uma versão, com aviso.AdicionadoFuncionaAdiciona um reconhecimento explícito, desativado por padrão, para reter evidência anônima#700
limitada…
Adiciona um reconhecimento explícito, desativado por padrão, para reter evidências anônimas limitadas com
#700 (issue no GitHub)Cache-Control: no-store, mantendo a omissão dos corpos com credenciais.
9 de setembro de 2026
10 adicionado9 alterado2 corrigidoAdicionadoFuncionaAdiciona prévias offline de prioridade de projeto e aplicação explícita e versionada de#694
políticas, com base nos fatos de stack salvos, preservando as escolhas do operador, com histórico atômico de políticas e explicações de prioridade coerentes nos relatórios humanos.
#694 (issue no GitHub)CorrigidoFuncionaCorrige a orientação sobre renderização de JavaScript, canonical, higiene de URLs e#692
#692 (issue no GitHub)notranslate, sem alterar verificações de runtime nem severidades.- CorrigidoFuncionaMantém as URLs de sitemap e robots do fixture de documentação na origem loopback efêmera.#690 (issue no GitHub)
AdicionadoFuncionaAdiciona cobertura portátil de checklist de projeto com um catálogo derivado da fonte…#686
Adiciona cobertura portátil de checklist de projeto, com um catálogo empacotado derivado da fonte, templates personalizados reutilizáveis, histórico de definições e evidências, gravações concorrentes otimistas, revisão explícita manual e de entregáveis, e visões offline de pendente, desatualizado e bloqueado, compartilhadas pela CLI, pelo MCP e pelos relatórios humanos vinculados ao projeto.
#686 (issue no GitHub)AdicionadoFuncionaAdiciona um resumo de status somente leitura do scan nativo para populações da fronteira…#685
Adiciona um resumo somente leitura do status do scan nativo, para populações da fronteira e resultados HTTP confirmados.
#685 (issue no GitHub)AdicionadoFuncionaAdiciona workspaces de projeto locais e portáteis com estados explícitos de checklist…#678
Adiciona workspaces de projeto locais e portáteis, com estados explícitos de checklist pendente e de preparação.
#678 (issue no GitHub)AdicionadoFuncionaRegistra no repositório a revisão das orientações do Google Search Central: 175 guias#677
lidos, seus rótulos, exclusões, data do snapshot e as três correções que ela gerou.
#677 (issue no GitHub)AlteradoFuncionaO
crawl-siteem modo URL agora grava um scan SQLite nativo à prova de colisão…#676O
#676 (issue no GitHub)crawl-siteem modo URL agora grava, por padrão, um scan SQLite nativo à prova de colisão na pastascans/do chamador.--out-dircontinua como rota legada explícita para diretório, enquanto a entrada por lista e as configurações de cache live/replay indicam essa rota, em vez de mudar o modo de coleta silenciosamente.AlteradoFuncionaBuilds de distribuição limpos agora incorporam proveniência validada do produtor para#675
scans SQLite nativos quando não há um checkout de código-fonte disponível.
#675 (issue no GitHub)AlteradoFuncionaSubstitui afirmações não suportadas de perda de sinal no 301 e de ausência de autoridade#671
no 302…
Substitui, na skill de auditoria empacotada, as afirmações não suportadas de perda fixa de sinal no 301 e de ausência categórica de autoridade de link no 302 por orientações sobre intenção permanente ou temporária e URL canônica de destino, citando o Google Search Central. Redirecionamentos temporários continuam válidos para mudanças temporárias; um código de status isolado não mede perda de ranqueamento.
#671 (issue no GitHub)AlteradoFunciona
render-check --viewport mobileagora usa uma única identidade diagnóstica estável de#670smartphone nas requisições brutas e nas feitas pelo navegador. Um
#670 (issue no GitHub)--user-agentexplícito está disponível pela CLI e pelo MCP, e cada comparação, completa ou parcial, registra a identidade efetiva e o tamanho da viewport.AdicionadoFuncionaAdiciona entradas
--scansomente leitura para análise de corpus duplicado e#669boilerplate, com cobertura do corpo retido e proveniência.
#669 (issue no GitHub)AdicionadoFuncionaAdicionado um catálogo de entradas de comando gerado automaticamente e documentada a#668
decisão sobre o armazenamento do scan, do cache HTTP e do journal de execuções.
#668 (issue no GitHub)AlteradoFuncionaRelatórios para o cliente em Markdown, CSV, XLSX, DOCX e de tarefas agora usam títulos de#660
problemas voltados ao leitor e as evidências salvas de reprodução, em vez de identificadores do registro ou nomes de coletores. Registros históricos sem evidência suficiente declaram essa limitação explicitamente, enquanto os artefatos de auditoria em JSON permanecem inalterados.
#660 (issue no GitHub)AdicionadoFuncionaAdiciona
project-factspara registrar fatos da stack do projeto após a criação,#648opcionalmente a partir de uma única passagem explícita de
#648 (issue no GitHub)tech-detectque respeita o robots.txt. Decisões inseridas pelo operador ficam acima das evidências detectadas, e uma detecção indisponível ou ambígua fica ausente, com o motivo registrado.AlteradoFuncionaColoca o controlador do projeto no início do README e apresenta o Screaming Frog como#648
segunda passagem…
Coloca o controlador do projeto no início do README e apresenta o Screaming Frog como uma segunda passagem de conferência cruzada, e não como padrão de paridade.
#648 (issue no GitHub)AdicionadoFuncionaInclui
examples/project-skeletoncom uma checklist inicializada e sem resultados, para#648que
#648 (issue no GitHub)project statusnele mostre contagens de cobertura em vez denot_initialized, e valida esse arquivo contra o catálogo atual.AdicionadoFuncionaAdiciona contratos de preparação de projeto, evidências de provedores, corpus salvo,#354
extração limitada, evidências de scan e de workflow/catálogo, com limites explícitos para as evidências retidas e para o progresso.
#354 (issue no GitHub)AlteradoFuncionaPerfis MCP e wrappers de progresso que preservam metadados exigem o SDK MCP opcional na#354
versão 1.29 ou posterior.
#354 (issue no GitHub)AlteradoFuncionaSimplifica o README em torno de fluxos de tarefa, comando e artefato, remove embeds
visuais desatualizados e contadores promocionais, e mantém links para as referências geradas da superfície atual da interface.
AlteradoFuncionaExpande o README com fluxos práticos de entrada até resultado, chamadas equivalentes de
CLI/MCP e limites precisos sobre o corpus retido, o navegador e os provedores.
8 de setembro de 2026
8 alterado2 corrigidoAlteradoFuncionaAlinha a documentação do artefato SQLite ao corpo nativo entregue, ao histórico e aos#666
contratos de…
Alinha a documentação do artefato SQLite ao corpo nativo, ao histórico e aos contratos de reanálise offline que já estão no código (#666). A tabela de campos da página tardia agora é verificada contra o mapeamento do importador, para que uma observação antiga em JSONL continue como NULL no SQL, e não vire um valor “limpo” inventado.
#666 (issue no GitHub)AlteradoFuncionaAuditorias nativas agora marcam como ignoradas as verificações de meta keywords,#659
canonical secundária, versão HTTP e amphtml quando os campos de origem não foram coletados.
#659 (issue no GitHub)CorrigidoFuncionaDeixa de ler, na via de renderização JavaScript, um cookie que o próprio site definiu#656
como credencial do operador, e informa explicitamente quando uma execução descarta DOMs renderizados (#656). Um navegador devolve tudo o que o
#656 (issue no GitHub)Set-Cookiedo próprio site lhe entregou. Assim, no instante em que uma página definia um cookie de sessão e depois pedia um subrecurso do mesmo origin — um script, uma folha de estilo, uma imagem, a forma comum da web —, o hook de requisição do renderizador lia oCookie:da rede e guardava o DOM serializado daquela página comoomitted/credentialed, numa execução comhttp.credential_headers = []. Cada renderização cria o próprio contexto de navegador, então a perda é por página, e não cumulativa: toda página que define um cookie perde o próprio DOM, e a execução informa suas páginas, links e contagens de escalonamento exatamente como faria se estivesse completa. Ocredentials_usedde um documento renderizado agora vem apenas daquilo que a execução foi configurada para enviar —http.credential_headersou um perfil persistente de navegador —, o quecrawl/sqlite_render.py::_policy_factsjá deriva e entrega ao renderizador; o renderizador monta o próprio cliente de rede sem credencial própria, então a rede não tinha nada a acrescentar. Um rastreamento com credencial configurada continua omitindo esses DOMs sobcredentialed, sem alteração, e o valor do cookie continua nunca sendo armazenado.AlteradoFuncionaAs contagens de renderização que uma flag
partialnão consegue expressar agora são#656nomeadas.
#656 (issue no GitHub)rendered_bodiesem um resultado decrawl-siteinforma quantos DOMs renderizados foram retidos e o motivo de cada um que não foi, e a CLI imprime isso junto da linha de conclusão, em vez de deixar tudo a cargo de uma flag de capacidade que diz “partial” tanto para um DOM ausente quanto para todos eles. Uma execução que não descartou nada não imprime nada extra. As contagens são lidas de volta do artefato do scan, então um scan concluído continua respondendo à mesma pergunta depois.AlteradoFuncionaColeta
og:urlem um rastreamento nativo, em vez de marcar todas as páginas como sem#654essa tag (#654).
#654 (issue no GitHub)rules.check_ogincluiog:urlentre asmissing_tagsde uma página sempre que o campo estiver vazio, mas o caminho nativo nunca lia essa tag: não haviaog_urlemPageRecord, nenhuma colunaog_urlemscan_v1.sqle nenhumOG:URLna projeção Internal:All quecrawl/evidence.pymonta. A coluna só existia do lado do Screaming Frog, ondenormalizesempre resolveuOG:URL; assim, uma exportação do site enxergava o valor real, e um rastreamento nativo do mesmo site acusava um defeito — um campo não medido apresentado como medido, em toda página de todo rastreamento nativo, independentemente do que a marcação dizia. Agora a tag é lida onde já são lidas as outras três (o parser já devolviaog:url), armazenada empages.og_urlanulável — anulável como qualquer outra coluna adicionada depois, para que um registro gravado antes da coleta continue distinguível de uma página que não declara a tag — e projetada comoOG:URL. Este é o lado de coleta da costura cujo lado de leitura o #646 corrigiu.tests/test_open_graph_seam.pyganha um terceiro site de teste, cujas páginas têm Open Graph mas não têmog:title, para que o achado realmente dispare e sua lista possa ser lida: uma página declaraog:urle não pode ser apontada como sem ela; a outra não declara e precisa ser apontada. O teste que importa audita as duas páginas duas vezes — uma a partir do rastreamento e outra a partir de uma exportação Internal:All que descreve as mesmas duas páginas — e exige o mesmo veredito. O #646 e o #654 foram ambos casos de dois caminhos discordando sem nenhum teste que os abrangesse.CorrigidoFuncionaDeixa de ler um cookie definido pelo site como credencial do operador, e informa quando#647
uma execução…
Deixa de ler um cookie definido pelo site como credencial do operador, e informa explicitamente quando uma execução descarta corpos (#647). Um rastreamento compartilha um único cliente HTTP, e esse cliente mantém um cookie jar: no momento em que qualquer resposta trazia
#647 (issue no GitHub)Set-Cookie, todas as requisições seguintes saíam comCookie:, e o gravador do corpus classificava a busca como autenticada. Em um site público comhttp.credential_headers = []ecredentials_acknowledged = false, isso descartou 33.001 de 40.920 corpos de página, e a execução informou suas páginas e links exatamente como se estivesse completa. Tudo o que é calculado a partir do HTML armazenado nesse rastreamento — detecção de quase-duplicados, profundidade e contagem de nós do DOM, participação de boilerplate, estrutura de títulos no corpo, reanálise offline — passou a cobrir 7.903 páginas, enquanto cada percentual por página no mesmo relatório cobria 40.920: duas populações apresentadas como uma. Uma captura é considerada credenciada quando a execução foi configurada para enviar um cabeçalho de credencial para aquele host, que é a única forma de um cabeçalho sensível chegar a uma requisição montada pelo rastreador —http.headersé recusado pela validação de configuração. Um rastreamento com credencial configurada continua omitindo esses corpos sobcredentialed, sem alteração.AlteradoFuncionaAs contagens que uma flag
partialnão consegue expressar agora são nomeadas.#647
#647 (issue no GitHub)html_bodiesem um resultado decrawl-siteinforma quantos corpos HTML de página buscados foram retidos e o motivo de cada um que não foi, e a CLI imprime isso junto da linha de conclusão, em vez de deixar tudo a cargo de uma flag de capacidade que diz “partial” tanto para um corpo ausente quanto para quatro quintos deles. Uma execução que não descartou nada não imprime nada extra. As listas de cabeçalhos de requisição e resposta redigidas agora mantêm os nomes dos cabeçalhos que a redação removeu, emx-seohead-redacted-headers, nunca os valores: duas respostas cujos corpos foram tratados de forma diferente antes registravam listas de cabeçalhos byte a byte idênticas, então quem lia o artefato não conseguia saber por que um corpo estava ausente.AlteradoFuncionaMove as entradas do changelog de
CHANGELOG.mdpara um arquivo por mudança na pasta#638changelog.d/…
Move as entradas do changelog de
#638 (issue no GitHub)CHANGELOG.mdpara um arquivo por mudança emchangelog.d/, para que um pull request deixe de conflitar com todos os outros que foram mesclados antes dele (#638). Cada branch adicionava sua entrada no topo de## Unreleased, o que fazia dessa única linha o ponto de disputa do arquivo: nove resoluções manuais em oito pull requests, em duas sessões, cada uma um re-push e uma nova execução de CI, e a resolução era sempre “manter nosso bloco, depois o deles”. Um conflito cuja resposta nunca varia não traz informação nenhuma, e é uma chance de perder um parágrafo enquanto se pensa em outra coisa. A correção de.gitattributesproposta na issue —CHANGELOG.md merge=union— foi medida e descartada antes disso: o union mescla linha a linha, então, quando as duas entradas contêm uma linha idêntica (uma linha em branco dentro de uma entrada já basta), ele mantém uma cópia e informa sucesso, apagando a linha da outra entrada sem conflito e sem aviso. Um primeiro teste, com linhas deliberadamente distintas, mesclou sem problemas e escondeu isso. Trocar um conflito ruidoso por perda silenciosa de dados é estritamente pior que o conflito, então foi enviada a correção estrutural.AlteradoFuncionaUm fragmento recebe o nome da issue que ele fecha (
changelog.d/638.md), a chave única#638de cada…
Um fragmento recebe o nome da issue que ele fecha (
#638 (issue no GitHub)changelog.d/638.md), a chave que é única para cada branch por construção: um pull request que fecha duas issues gera dois fragmentos, um por issue, e uma mudança que não fecha nenhuma gerano-issue-<slug>.md. Um fragmento contém a entrada exatamente como ela deve aparecer no changelog — um ou mais bullets de primeiro nível com suas linhas de continuação, sem front matter e sem invólucro —, de modo que as entradas em prosa de vários parágrafos que este arquivo traz são preservadas byte a byte, sem serem reformatadas em uma linha.python scripts/build_changelog.pyas incorpora em## Unreleasedna hora da release, ordenadas pelo número da issue e não pela ordem que o sistema de arquivos devolver, e--pruneremove os fragmentos que foram incorporados. A montagem substitui toda a região entre dois comentários-marcadores, em vez de inserir algo nela, então executá-la duas vezes produz o mesmo arquivo nas duas vezes, tenham ou não os fragmentos sido removidos entre elas. OCHANGELOG.mdem si não é regenerado a cada pull request, de propósito: um gate que o mantivesse sempre sincronizado colocaria as duas branches de volta no mesmo arquivo e recriaria o conflito que isto elimina.AlteradoFuncionaOs gates de documentação que liam
CHANGELOG.mderam o risco, porque um gate que para de#638verificar…
Os gates de documentação que liam
#638 (issue no GitHub)CHANGELOG.mderam o risco, porque um gate que deixa de verificar algo em silêncio é pior que os conflitos. Ambos foram encontrados e agora cobrem os fragmentos:tests/test_docs_drift.pytinhaCHANGELOG.mdemPUBLIC_MARKDOWN, então o gate somente em inglês, o gate de “referencia apenas comandos existentes” e o gate de contagens desatualizadas agora leem tambémchangelog.d/*.md, e os dois gates de deriva de contagem ignoram um fragmento pelo mesmo motivo que ignoram o changelog — uma entrada registra o que era verdade no momento em que foi escrita.tests/test_doc_counts.pyexclui deliberadamente o changelog da sua varredura de contagens ao vivo, e sua lista de arquivos nunca chega achangelog.d/, o que dá a mesma resposta pelo mesmo motivo;tests/test_doc_commands.py,tests/test_docs_commands_execute.pyetests/test_examples_gate.pynunca leem o changelog. Um novotests/test_changelog_fragments.pyfixa cada uma dessas respostas, junto com a nomeação de fragmentos, a ordem determinística, a montagem idempotente e o fato de que duas branches concorrentes simuladas, cada uma adicionando um fragmento, se mesclam sem conflito.
Anteriores (data não registrada)
23 adicionado30 alterado17 corrigidoCorrigidoFuncionaContinua a fazer fingerprinting de uma página cujo site envia um cabeçalho
Set-Cookiesem valor (#651).
Um cabeçalho sem nenhum par
name=value—Set-Cookie: Secure; HttpOnly, queemall.byenvia ao lado de dois cookies bem formados — viraCookie(name='Secure', value=None)no jar, ehttpx.Cookies.__getitem__levantaKeyErrorpara ele. Por isso,dict(resp.cookies)falhava em um nome que o próprio iterador do mapeamento tinha produzido:tech-detectterminava com código 1, com umerror: 'Secure'seco e sem JSON na saída, para uma página que tinha sido buscada com sucesso; o MCPseo_tech_detectpropagava oKeyErrorpara quem chamou; esite-auditvoltava em silêncio com toda a seção de tecnologias ausente.detect_techagora percorre o jar de cookies. Um nome sem valor é mantido com valor vazio, em vez de descartado, porque várias assinaturas (BITRIX_SM_GUEST_ID,craft_session,wfvt_) casam apenas pelo nome do cookie, e descartar a entrada perderia esse sinal. Mas ele nunca é normalizado em silêncio como um cookie comum: os nomes são informados emmalformed_cookiese citados em um problema, de modo que um cabeçalho que o site enviou quebrado continue sendo um fato sobre o site. Uma resposta só com cookies bem formados não é afetada e informa uma lista vazia.AlteradoFunciona
render-checkvolta a medir sites compactados em vez de considerá-los quebrados (#650).A rota de renderização fixada lia a origem pelo stream não decodificado do httpx e entregava esses bytes ao Playwright junto com o
content-encodingda origem.route.fulfillnunca aplica uma codificação de conteúdo ao corpo que recebe, então o Chromium interpretava o gzip comotext/htmle montava um DOM a partir do fluxo comprimido: sem título, sem h1, sem canonical, sem links, e um tamanho renderizado igual ao tamanho transferido. Todo site que compacta seu HTML — quase todos — voltava comok: false, reason: incomplete_render, e a mensagem culpava a renderização, sugerindo--wait domcontentloadedou um--timeoutmaior, quando a renderização tinha terminado perfeitamente.seohead.techregistrava 22.435 bytes renderizados contra 121.793 brutos; agora registra 123.048, com o título real e 31 links. A rota passa a ler a entidade já decodificada, removecontent-encodingdo que encaminha (content-lengthjá era removido como hop-by-hop, então o Playwright informa o tamanho do corpo que de fato recebeu) e pede à origem apenas as codificações que este cliente sabe decodificar, em vez de repassar o convite que o próprio Chromium faz parabrezstd. Uma codificação que chegue sem decodificação aborta a requisição e se identifica pelo nome, porque deixá-la passar reproduziria o bug em silêncio. O limite de bytes agora conta bytes decodificados, que é o corpo que o renderizador enxerga — antes, uma bomba de compressão passava pelo limite já comprimida.AlteradoFuncionaLê o Open Graph de um rastreamento nativo pela chave que o parser de fato grava (#646).
parse_htmlarmazena cada tag pelo nome completo da propriedade —{"og:title": ...}, como diz a própria docstring —, ecrawl/collect.pypedia ao mesmo dicionário"title","description"e"image".dict.getrespondiaNoneem todos os casos, entãoog_title,og_descriptioneog_imageficavam vazios em todas as páginas de todo rastreamento nativo já executado: 0 de 40.920 páginas tinham algum desses valores na execução que revelou o problema, em um site cujas páginas publicam Open Graph. Era a regra central do repositório invertida — um campo não medido lido como medido —, e o problema se propagou, porquecrawl/evidence.pyprojeta essas colunas emOG:Title,OG:DescriptioneOG:Imagedo quadro Internal:All, então uma verificação via rastreamento nativo via vazio, enquanto via exportação do Screaming Frog do mesmo site via o valor real. O contrato de honestidade decheck_ogescondeu o dano em vez de mostrá-lo: sem nenhuma coluna OG preenchida em lugar nenhum, a verificação era ignorada, e um site com Open Graph era auditado de forma idêntica a um site sem ele. O parser não mudou; só o lado de leitura foi corrigido. Um novotests/test_open_graph_seam.pyfaz o rastreamento de dois sites de teste em loopback e acompanha o valor do parser atépages.jsonl, depois até a tabelapagesdo artefato de scan e por fim até as colunasOG:*do quadro; rastreia um segundo site sem Open Graph para separar “vazio porque ausente” de “vazio porque não foi lido”; e fixa o formato de chave do parser no mesmo arquivo. A falha era dois módulos corretos discordando sobre o nome de uma chave, sem nenhum teste que abrangesse os dois.AlteradoFuncionaResponde “este site está bem linkado, e onde está linkado mal”, ampliando o registro de
157 para 161…
Responde à pergunta “este site está bem linkado, e onde está mal linkado”, ampliando o registro de 157 para 161 verificações e adicionando a skill
internal-linking(#634). As peças já existiam — cada aresta com sua posição, âncora e flag nofollow na tabelalinks,ORPHAN_PAGE,INLINK_BOILERPLATE_ONLY,LOW_LINK_SCORE—, mas nada as transformava em uma resposta sobre o grafo. Uma auditoria de 40.920 páginas trouxe o título errado por horas por causa disso: 66% do sitemap foi reportado como inalcançável por links internos, um número produzido pela subtração da contagem de URLs do rastreamento da contagem do sitemap, o que mede “o rastreador não chegou lá”. Percorrendo as 5.252.235 arestas do próprio artefato a partir da home, a alcançabilidade ficou em 91,9%. O defeito real era a profundidade: 23.742 páginas — 58% do site — estavam a mais de dez cliques da home, e a mais profunda ficava a 3.005, porque o arquivo é uma lista encadeada de links “próximo post” em vez de uma árvore. A profundidade de cliques agora é o título que a auditoria imprime.summary.internal_linkingtraz o histograma, o máximo, a divisão entre alcançáveis e inalcançáveis, as arestas internas por posição na página e quantas arestas repetem outra aresta, eaudit.mdapresenta isso ao lado do resumo de saúde. O percurso começa na URL com que o rastreamento de fato começou, nunca empages.crawl_depth: essa coluna registra onde o rastreador por acaso alcançou uma URL, e um rastreamento semeado pelo sitemap registra 0 para a maior parte do site, então um percurso semeado a partir dela descreveria outro lugar. Quando nenhuma URL inicial foi registrada e mais de uma página declara profundidade 0, a medição se recusa a rodar e informa quais são.AlteradoFuncionaQuatro verificações leem esses números.
DEEP_CLICK_DEPTHdispara em uma página indexável cujo caminho mais curto a partir da URL inicial excedethresholds.click_depth_max(padrão 10, e cada problema informa o número que usou).DUPLICATE_INTERNAL_LINKdispara em uma página que escreve o mesmo destino e a mesma âncora mais de uma vez: no site acima, 509.744 de 1.134.307 arestas — 44,9% — eram repetições, e se tratava de um mesmo cabeçalho emitido duas vezes, com a segunda cópia removida por JavaScript, um defeito de template que exigiu um script escrito à mão para ser encontrado.LINK_INSIDE_HEADINGeIMAGE_LINK_WITHOUT_TEXTprecisam do que a região da página de um link não consegue informar — a cadeia de ancestrais da própria âncora e o seu conteúdo —, então um rastreamento nativo agora registra umlink_placement_jsonpequeno e limitado por página, ao lado do esquema de títulos, e ambas as verificações são ignoradas pelo nome em uma exportação do Screaming Frog, em vez de rodar sem ter o que analisar.AlteradoFuncionaAs regras de honestidade que o restante do analisador mantém valem em todo o conjunto.
Uma aresta sem posição registrada é contada como
unclassifiede nunca é somada acontent:link_position.classifyvem desligado por padrão, o que deixa isso em todas as arestas, e uma execução nesse estado deve ser lida como “ninguém olhou”, e não como um site cujos links são todos texto do corpo. Uma posição ausente da distribuição é informada como “nenhuma aresta classificada aqui”, e não como uma região que o site não tem — as regras são testadas em ordem, e um menu dentro de<header>casa primeiro comnav. Um rastreamento parcial retira o veredito de profundidade de cliques esteja ou não disparado, porque uma fronteira nunca buscada pode conter o caminho mais curto; uma verificação que não encontra nada em silêncio seria lida como “todas as páginas estão dentro do limite”.CorrigidoFuncionaDeixa de reportar como limpa uma verificação condicionada a um requisito quando ela nunca
foi avaliada (#635).
H2_MISSINGsó dispara quando uma configuração definerequirements.require_h2, e o padrão é false, então em uma execução comum esse ramo é inalcançável. Não deixava nenhum rastro disso: a cobertura contava a verificação entre as silenciosas — o balde que significa “rodou em todas as páginas e não encontrou nada” — e o leitor era informado de que o site tinha passado em uma verificação que ninguém executou. Na auditoria que revelou o problema, 61% das páginas do site não tinham nenhum H2, e 5.066 delas tinham mais de 800 palavras, então a verificação teria disparado milhares de vezes. Agora ela é declarada ignorada pelo nome, com um motivo que cita a configuração que a desligou, de modo que a resposta seja “não avaliada, e eis como avaliar”, e não silêncio.require_canonicaltem a mesma forma e recebe o mesmo tratamento; seu padrão é true, então não estava produzindo uma leitura errada ainda, mas agora não pode começar a produzir.CorrigidoFuncionaCorrige o cabeçalho da lista de tarefas que mostrava “Audit Tasks — None” em qualquer
auditoria sem projeto (#640).
Corrige o cabeçalho da lista de tarefas que mostrava “Audit Tasks — None” em qualquer auditoria cuja execução não tenha registrado um projeto (#640).
render_tasks_mdmontava o cabeçalho comsrc.get("project", "site"), mas"project"é sempre uma chave presente no blocosourceda lista — ela é definida na montagem a partir derun.get("project"), então uma execução sem projeto grava ali o valorNoneem vez de deixar a chave ausente, e o padrão dodict.getsó vale para chave ausente, nunca para uma que contémNone. Um rastreamento nativo e uma reanálise deixamprojectsem valor, então toda lista montada a partir de qualquer um dos dois recebia a palavra literal “None” como título. O cabeçalho agora usaorcomo fallback, o que captura umNonearmazenado, e recorre àstart_urlou aosourcedo site antes de desistir — a mesma ordem queseohead.reports.facts.crawl_domainjá usava para resolver o nome de um site a partir do seu blocorun; essa função agora é exportada e reutilizada aqui, em vez de reinventada, de modo que uma lista montada a partir de uma auditoria sem projeto nomeie o site real, e não a palavra “site”.seohead.reports._normalize_sf_audittinha a mesma forma latente uma linha ao lado (run.get("project") or "", emreports/__init__.py) — já protegida contra umNonearmazenado, mas seu fallback era um domínio vazio em vez da URL que a execução também conhece, então o cabeçalho “SEO Audit: ” dos docx/md que ela alimenta ficava em branco nas mesmas situações. Agora ele usa a mesma resolução decrawl_domaincomo fallback.AlteradoFuncionaLê o esquema de títulos como sequência e como mapa da página, ampliando o registro de 155
para 157 verificações (#632). As oito verificações de título existentes julgam os títulos como um conjunto: podem afirmar que uma página tem um H1 e quatro H2, e nada além disso. Assim, uma página cuja ordem no DOM é
H2, H2, ..., H1, H2passava em todas elas, e também passava uma página cujos H2 eram todos rótulos de menu no cabeçalho — encontrado em um site no ar como um template de artigo com dezoito títulos antes do próprio H1, e reportado como limpo em títulos. O que faltava era a evidência, não a regra:pagesguardavah1,h1_2eh2— três strings sem ordem nem lugar. Um rastreamento nativo agora registra o esquema completoh1-h6em ordem de DOM, cada título com seu nível, texto e região da página, em uma nova coluna anulávelheading_outline_json, eHEADING_BEFORE_H1eHEADING_IN_PAGE_CHROMEo leem. A região reutiliza a taxonomia que a classificação de links já usa (nav,header,sidebar,footer,content,other), de modo que “no cabeçalho” signifique a mesma coisa sobre um título que já significa sobre um link. Um título que nenhuma regra de posição casou só é posicionado em relação à área de conteúdo quando o documento nomeou uma — um<main>, um[role=main], um<article>ou um seletor configurado; quando a raiz de conteúdo recai no<body>inteiro, chamar um título de “conteúdo” não significaria mais do que “algum lugar da página”, então a região é registrada como não medida e a página entra nas verificações ignoradas da execução com esse motivo, sem ser aprovada como limpa nem marcada como defeito. A ordem não precisa de região, entãoHEADING_BEFORE_H1continua respondendo para essas páginas. Uma exportação do Screaming Frog não traz esquema nenhum, e as duas verificações são ignoradas pelo nome ali.CorrigidoFuncionaMantém uma coleta concluída quando a auditoria que vem depois dela falha (#627).
Um rastreamento nativo de um site no ar passou vinte minutos reunindo 600 páginas em um artefato
--scan-oute depois imprimiuerror: 'rel_next_2'— ostr()de umKeyErroré só a chave, e nada além. Sem fase, sem traceback e sem nenhum sinal de que todas as páginas coletadas estavam completas e prontas para reanálise no arquivo. A coleta grava suas linhas e fecha antes de a auditoria começar, então qualquer exceção levantada depois desse ponto é um comportamento errado do analisador, nunca do rastreamento; uma exceção inesperada nessa etapa agora é nomeada pela fase, traz o tipo da exceção além da mensagem e aponta para o artefato retido e para o comando que o reanalisa, exatamente como o caminho de auditoria grande já fazia. A execução informaaudit_available: falsecom esse motivo, em vez de sair com a exceção, ecrawl-sitetermina com código 2 nesse caso — a mesma terceira resposta que a contradição do log-scan já usa, porque 0 leria como “a auditoria rodou e encontrou isto” e 1 como “o comando não produziu nada”, e nenhuma das duas coisas é verdade para um rastreamento cujas evidências sobreviveram. O próprioKeyErrornão se reproduziu: o mesmo comando contra o mesmo site na main atual foi concluído, então isso muda o que acontece quando uma auditoria falha, não o que causou aquela falha.CorrigidoFuncionaDeixa de perder a auditoria de um rastreamento concluído por causa de um orçamento fixo
de 30 segundos de inspeção ao reabri-lo (#631).
NativeScan.open()lê o cabeçalho de um scan nativo por meio deinspect(), que também executaPRAGMA quick_checkePRAGMA foreign_key_checksobre o banco inteiro — uma verificação de segurança real, mas cujo custo cresce com o tamanho do artefato, enquanto o orçamento não crescia. Um rastreamento de 3,5 horas e 40.920 páginas terminou de coletar tudo o que se propôs a coletar e depois não produziu auditoria nenhuma, porque reabrir o artefato resultante de 1 GB exigia cerca de 48 segundos de validação contra um orçamento fixo em 30. Pior: a falha não dava nenhum motivo para suspeitar de orçamento — o aborto por prazo chega do SQLite como umsqlite3.OperationalError("interrupted")seco, e isso era embrulhado tal e qual emcannot inspect native scan: interrupted, indistinguível de um arquivo realmente corrompido. Os dois problemas foram corrigidos. O orçamento padrão agora é derivado do tamanho do artefato (um piso de 30 segundos para arquivos pequenos, mais uma folga generosa por byte, bem abaixo da taxa de validação medida de cerca de 22 MB/s, já que isso é um teto contra uma leitura travada, e não uma meta de desempenho) — umtimeout_secondsexplícito de quem chama continua prevalecendo. E um aborto por prazo agora levanta umScanErrorque informa o orçamento, o tempo decorrido e o tamanho do artefato, para que um operador consiga distinguir um arquivo grande e lento de um arquivo corrompido, em vez de ler “interrupted” como algo que ele fez errado.AdicionadoFuncionaAdiciona
crawl-site --resume <scan.sqlite>(#619).NativeScan.resume_snapshot(), a tabelaresume_statee o gravador que a preenche já existiam desde que o artefato de scan foi projetado, ecrawl_to_scanjá continuava um arquivo existente — mas só para quem reproduzisse byte a byte as configurações efetivas originais, e nenhuma interface expunha isso. Apontar--scan-outpara um artefato interrompido com qualquer flag alterada era recusado como incompatibilidade de configuração, então, na prática, um rastreamento interrompido (6.516 de 34.635 páginas, em um site de terceiros) tinha de começar do zero.--resumerecebe apenas o artefato: a URL inicial e a configuração efetiva completa são lidas de volta do arquivo, porque são o que a fronteira armazenada foi construída com, e qualquer outra flag que molda o rastreamento passada junto é recusada em vez de aplicada. Um scan gravado por outra versão do produtor, registrado para outra URL inicial, já concluído, derivado de uma reanálise ou executado com cabeçalhos de credencial que só consegue guardar redigidos é recusado pelo nome só a partir do arquivo, antes que uma única requisição seja disparada.crawl-sitetambém passa a imprimir uma linha no stderr ao sair, dizendo se o rastreamento terminou ou parou antes, por qual motivo e como continuá-lo — exceto após um orçamento de URLs ou de duração, que uma retomada também lê de volta e portanto não pode repassar; nesse caso a linha diz isso, em vez de oferecer um comando que não faz nada.run.crawl_resumedcontinua sendo o registro durável: um rastreamento retomado do site de teste offline busca cada URL exatamente uma vez entre os dois processos e produz uma auditoria idêntica à de um rastreamento sem interrupção em todos os campos, exceto naquele.CorrigidoFuncionaImpede que
render-checkdeclare uma página não renderizada como limpa, e que descarteevidências de HTML bruto (#642).
Dois efeitos da guarda de #623, ambos em
render.py, afetamrender-check. Primeiro, uma renderização que estourou o tempo no marco de carregamento recorre a ler o DOM emdomcontentloaded— correto em si —, mas, quando nenhum script tinha rodado até ali, o DOM renderizado era igual ao HTML bruto, o comparador não encontrava nada e a execução informavaok: True,js_dependent: Falsee o único problema “Raw HTML and rendered DOM are materially equivalent; JavaScript rendering does not determine SEO-visible content”, classificado como aviso, sobre uma página que ninguém tinha renderizado.wait_reachedregistrava a verdade, mas o relatório da auditoria de site carrega para o relatório apenas o texto dos problemas, então a verdade nunca chegava. Uma execução que recorreu a um marco anterior agora diz isso na própria lista de problemas, retém o atestado de ausência de falhas e informajs_dependent: None— esta execução não sabe —, em vez deFalse. Isso acontecia com o padrão--wait load, e não apenas comnetworkidlepedido explicitamente. Segundo, a guarda devolvia sua única afirmação “a comparação está indisponível” antes de chegar ao ramo de casca vazia, e o retorno antecipado derender_checkomitia a chaveempty_shellpor completo — então um ponto de montagem vazio de aplicação de página única, quedetect_empty_shell()lê da resposta bruta do servidor e que não precisa de navegador algum, era descartado junto com a renderização que falhou. Como uma casca de SPA é exatamente a página cuja renderização estoura o tempo, o problema se perdia justamente onde mais importava. Um problema derivado da metade bruta agora sobrevive a uma renderização inacabada; só os derivados da metade renderizada são suprimidos. Em um rastreamento, uma sonda de renderização que não chegou a um veredito agora vai parapatterns_unprobedcom seu motivo (canal de #626), em vez de contar como um padrão medido e considerado sem necessidade de renderização.AlteradoFuncionaInforma um robots.txt ilegível como fato sobre o site, não como erro interno (#629).
EMPTY_ROBOTS— o substituto que_fetch_robotsdevolvia em todos os caminhos em que o robots.txt não podia ser lido — ainda tinha o formato de robots já analisado, anterior ao parser ganhar grupos e sitemaps. O caminho de sucesso devolve o formato deparse_robots, e esse é o único formato que o contextorobots_summarydo artefato de scan aceita; assim, no modo--scan-out, um rastreamento era abortado comnative parsed robots summary is invalidsempre que o robots.txt estava inacessível, respondia 429 ou 5xx, redirecionava para fora do host, entrava em loop, passava do limite de saltos ou devolvia um corpo que não eratext/plain— ou quando era um 404 simples, que não é erro nenhum, mas o caso “sem restrições” da RFC 9309 e o mais comum dos sete. As duas saídas documentadas se perdiam atrás daquela única linha: um robots.txt ausente agora permite o rastreamento sem restrições novamente, e um robots.txt indisponível interrompe a execução com a nota dizendo qual das seis formas de falha ocorreu. O modo de diretório legado nunca notou o problema, porque nada lê as chaves antigas. Encontrado em um site no ar cujo robots.txt redireciona com 302 para um endpoint de sincronização de cookies, para qualquer user agent que não reconhece.CorrigidoFuncionaCorrige
escalate(), que contava uma sonda de renderização falha como “não precisa derenderização” (#626).
Corrige
escalate(), que contava uma sonda de renderização falha como “este padrão não precisa de renderização” (#626). Ele amostra uma URL por padrão de template para decidir se aquele padrão precisa de uma busca mais completa, renderizada com JavaScript, mas, quando todas as amostras de um padrão falhavam ao sondar — um erro ao iniciar o navegador, um timeout ou uma renderização incompleta, os modos de falha comuns de um rastreamento real —, ofor/elseainda registrava o padrão como sondado, e ele acabava nem escalonado nem listado entre os padrões que a execução não conseguiu avaliar. Isso invertia a regra central do projeto: evidência ausente ou não medida nunca pode parecer limpa. Um padrão sobre o qual nada se aprendeu era rastreado de forma estática em silêncio e reportado do mesmo jeito que um padrão realmente medido e considerado sem necessidade de renderização.EscalationResultagora informa esse padrão empatterns_unprobed, junto dos padrões cortados por prazo que já eram rastreados ali, e registra o motivo de falha da própria sonda no novopatterns_unprobed_reasons, para que um relatório possa dizer “este padrão não foi avaliado” em vez de sugerir que foi. Um padrão com pelo menos uma sonda bem-sucedida não é afetado: isso muda apenas o que acontece quando todas as sondas de um padrão voltam comok: False.CorrigidoFuncionaImpede que
render-checkinforme uma renderização inacabada como defeito do site (#623).Quando a renderização não se completava, o snapshot renderizado voltava sem título, sem
h1, sem canonical, com zero links e com um quinto dos bytes da resposta bruta — e o comparador lia essa vacuidade como evidência sobre o site, emitindo “the title changes after JavaScript” sobre um título que a renderização nunca leu e “the canonical is injected by JavaScript” sobre um canonical que nunca viu. Em uma auditoria ao vivo, isso gerou quatro problemas errados e confiantes em sequência, do tipo que manda um desenvolvedor caçar um bug de JavaScript que não existe. Agora o par é avaliado antes de ser comparado: quando a resposta bruta traz marcos estruturais e o documento renderizado não traz nenhum deles, com um tamanho que é uma fração do bruto, a verificação retornaok: falsecomreason: "incomplete_render", um motivo nomeado que traz os dois tamanhos em bytes e os dois snapshots para inspeção — sem problemas, e comjs_dependent: nullem vez defalse, porque a execução não sabe.site-auditregistra isso emsummary.tools_failed, onde pertence uma verificação não medida. A detecção é deliberadamente estreita: um único marco sobrevivente, ou um documento renderizado com pelo menos metade do tamanho da resposta bruta, é comparado como antes, e uma página sem título e sem links dos dois lados é medida e apenas vazia, não marcada como não medida. Um título que um script realmente reescreve continua disparando seu problema. A estratégia de espera também lida com a causa comum: um site cujos scripts de analytics, chat ou anúncios com long-polling nunca deixam a rede ficar ociosa estourava o tempo da verificação inteira sob--wait networkidle, e agora recorre a ler o DOM emdomcontentloaded— sem uma segunda navegação —, com uma breve espera para scripts adiados, ewait_reachedregistra de qual marco o snapshot realmente veio. Uma página cujo DOMContentLoaded nunca disparou continua sendo uma falha de renderização, não uma renderização incompleta.AlteradoFuncionaDá ao
crawl-siteuma linha de progresso ao vivo (#619, metade de progresso).Um rastreamento nativo imprimia sua taxa efetiva de requisições e depois nada até terminar; em um site de 34.000 páginas, a única forma de saber que ainda estava trabalhando era ver o arquivo de scan crescer no
ls -la. Agora a linha se atualiza no lugar em um TTY, com páginas buscadas, URLs conhecidas até o momento, o percentual desse conjunto, a taxa atual de requisições numa janela móvel, o tempo decorrido e o tamanho do artefato de scan quando--scan-outestá gravando um. O que ela deliberadamente não faz é sugerir um total que não pode conhecer: um rastreador descobre a própria carga de trabalho, então o denominador éfetched + queued, limitado ao orçamento de URLs, é rotulado comoknowne não comototal, e uma linha de cabeçalho impressa uma vez informa que a fronteira ainda está crescendo e que o percentual não é uma estimativa de quando a execução vai terminar. Uma taxa não mensurável aparece comorate n/a, nunca como0.0 req/s. Os dois números vêm das estruturas do próprio rastreamento — para um scan SQLite, da mesma consultaresume_snapshotque o laço de coleta usa como guia —, de modo que o que aparece na tela é o que o artefato contém naquele instante, e não um contador paralelo que possa se desencontrar dele. Uma saída não interativa (um pipe, um arquivo de log, CI) recebe uma linha simples a cada 30 segundos, em vez de redesenhos com retorno de carro, e um novo-q/--quietsilencia tanto a linha de progresso quanto a linha de taxa de inicialização, deixando intacto o resultado JSON na saída padrão.AlteradoFuncionaFecha as três linhas de paginação que #385 deixou abertas, levando o registro de 152 para
155 verificações.
PAGINATION_MULTIPLEePAGINATION_URL_NOT_IN_ANCHORreportam uma página que declara dois sucessores diferentes, ou uma cuja URL declarada não é também uma âncora na mesma página. Os sucessores são comparados depois da normalização de URL — a mesma identidade que a metade de âncoras usa —, então/blog/page/2e/blog/page/2/vindos de dois plugins são um só sucessor escrito de duas formas, e não uma série ambígua.PAGINATION_URL_NOT_IN_ANCHORprecisa do inventário completo de links da página e lê a exportação All Inlinks para isso;PAGINATION_MULTIPLEnão precisa, e agora lê primeiro as colunas mais leves de ocorrênciarel="next" 2/rel="prev" 2doInternal:All, do mesmo jeito queCANONICAL_MULTIPLEjá responde a partir deCanonical Link Element 2— All Inlinks é só um fallback para um perfil cujoInternal:Allfoi gravado sem essas colunas.PAGINATION_SEQUENCE_ERRORreporta uma quebra em uma sequência de números de página que a série de outra forma segue, conforme a ressalva da própria issue: uma série pode começar em um número diferente de um, um passo não é uma quebra, e uma série cujas URLs não declaram número de página é marcada como não avaliada, em vez de julgada contra uma numeração que teria de ser inventada. Toda série que ficou sem julgamento é listada entre as verificações ignoradas da execução, com o motivo verdadeiro *para aquela série* — um passo, um ciclo, uma série curta demais para conter uma sequência e um número de página ilegível são quatro afirmações diferentes, e três delas descrevem séries cujas URLs declaram todas o seu número. A contagem é por série, não por execução, então o formato usual do WordPress (a página um em/blog/sem número, e as demais em/blog/page/N/) não pode desaparecer atrás de uma série julgável em outro ponto do mesmo rastreamento.AdicionadoFuncionaAdiciona um gate de cobertura de veredito (#98):
test_check_producer_gate.pyprovavaque cada ID…
Adiciona um gate de cobertura de veredito de verificações (#98):
test_check_producer_gate.pyprovava que cada ID de verificação estava registrado e que cada funçãocheck_*era despachada, mas não dizia nada sobre se a conclusão de uma verificação chegou a ser provada verdadeira diante de um marcado que de fato tem o defeito, nem sobre o marcado que não tem — exatamente a lacuna que deixou #94, #95 e #96 passarem por todos os testes existentes enquanto ainda disparavam errado em sites no ar.test_check_verdict_coverage.pyvarretests/de forma estrutural (AST, não uma lista fixa de chamadas) em busca das duas metades por verificação, e reprova o build para qualquer verificação recém-adicionada ao registro sem um teste dos dois lados ou uma isenção nomeada e fundamentada. Das 152 verificações do registro, 88 já tinham prova dos dois lados; um novotest_check_verdict_gaps.pyfecha mais 22 lacunas de baixo custo para teste que a varredura revelou (tamanho e duplicação de title e description, H1 duplicado, presença de H2, higiene de URL, verificações de diretivas e marcação, códigos de resposta e as duas verificações de exportações filtradas nativas). As 64 restantes são nomeadas, não escondidas, na lista de catracaKNOWN_UNCOVEREDdo gate — essa lista deve diminuir à medida que a cobertura chega, e nunca pode crescer para admitir uma verificação adicionada depois que o gate existia.CorrigidoFuncionaCorrige um defeito na seleção de grupos do robots.txt que deixava um
User-agentembranco anular a política padrão (#566).
Corrige um defeito na seleção de grupos do robots.txt que deixava um valor
User-agentem branco anular a política padrão de um site (#566). Uma linhaUser-agent:sem nada, ou uma cujo nome de bot foi engolido por um comentário inline (User-agent: # old bot rule), era analisada como um token vazio._rules_fortratava esse token como qualquer outro nome literal: um prefixo de comprimento zero casa com todos os agentes, e, por contar como correspondência *nomeada*, ele superava o grupo realUser-agent: *do arquivo para todo crawler que o arquivo não menciona. Um robots.txt cuja única regra substantiva eraUser-agent: * / Disallow: /passava, portanto, como totalmente rastreável — tanto no relatório de acesso dos bots de IA quanto no controle de busca do próprio crawler ao vivo, que chama o mesmois_allowed. Tokens em branco agora são ignorados, de modo que esse grupo não nomeia ninguém e o grupo curinga se aplica; o grupo nomeado mais específico continua vencendo, e um robots.txt que não nomeia ninguém continua significando que tudo é permitido.CorrigidoFuncionaCorrige quatro defeitos de seleção de exportação e de validação que deixavam uma
auditoria apresentar…
Corrige quatro defeitos de seleção de exportação e de validação de execução que deixavam uma auditoria apresentar um resultado que não podia sustentar (#209, #210, #215, #216). O matcher de
internal_allexigia apenas o token de nome de arquivointernal, então uma aba Internal parcial por tipo (por exemplointernal_html.csv, sem nenhuma linha não HTML) satisfazia a exportação mestre obrigatória Internal:All sem nenhum aviso de mestre ausente; agora o matcher também exigeall.discover_exportsescolhia o primeiro candidato de uma chave lógica na ordem alfabética dos nomes quando dois arquivos casavam com ela (por exemplointernal_all.csveinternal-all.csvpresentes com linhas diferentes), descartando o outro em silêncio e sem nada nos metadados da execução para indicar que houve uma escolha; agora ele levanta erro, nomeando todos os candidatos.run_sfescolhia a subpasta com timestamp mais recente dentro de--out, independentemente de quando ela foi criada, então uma reexecução que saía com código 0 sem gravar nada (uma falha de inicialização que o Screaming Frog não reporta como saída diferente de zero) podia devolver as exportações de uma invocação anterior como se fossem novas; agora compara com um snapshot tirado antes de o processo começar e falha de forma explícita quando nada novo aparece.build_commandsó acrescentava--auth-configquando o arquivo de perfil informado já existia, iniciando em silêncio um rastreamento não autenticado quando o caminho tinha um erro de digitação ou tinha sido apagado — adequado para o padrão opcionalseospiderconfig, errado para um perfil que quem chamou pediu explicitamente; agora umsf_cli.auth_configexplícito ausente levanta erro antes de o Screaming Frog iniciar.CorrigidoFuncionaCorrige dois defeitos de extração de conteúdo em
seohead/checks/parser.py(#138, #140).collapse_whitespacedecodificava entidades HTML uma segunda vez por cima da decodificação única que o parser lxml do BeautifulSoup já faz em todo valor quetag.get_text()/tag.get(attr)entrega a essa função — um no-op silencioso em marcação comum, mas, em uma página cujo CMS ou pipeline de importação já tinha escapado as entidades duas vezes (um artefato real e frequente), transformava uma sopa de entidades visivelmente quebrada em texto com aparência limpa e encurtava o comprimento informado abaixo do que uma aba do navegador ou um snippet de SERP realmente exibe, invertendo nos dois sentidos as verificações de tamanho de title/description. A função agora não decodifica mais nada. Além disso, a extração de links e de URLs de origem percorria o documento inteiro sem condição, então um<a>/<img>que existia apenas dentro de um<template>inerte — nunca parte do documento renderizado pela especificação HTML, nunca requisitado por um navegador ou crawler a menos que um script o clonasse — era reportado como link real na página e de fato buscado porspider.py, o mesmo modo de falha de URL fantasma já fechado para<base href>em #4; ambos os extratores agora ignoram os descendentes de<template>.<noscript>é deliberadamente mantido acessível ali, diferente da extração de texto: é marcação de fallback real e definida pela especificação, que um cliente com JavaScript desativado (e a passagem de rastreamento sem renderização dos mecanismos de busca) de fato carrega, e excluí-la esconderia do auditor uma URL genuinamente buscável. A contagem de palavras também deixa de contar o texto de descendentes de<svg>/<math>como corpo de texto (o<title>de acessibilidade de um sprite de ícones, o<text>de glifos, a notação MathML) — um cabeçalho com 20 ícones podia dobrar a contagem de palavras reportada em relação ao conteúdo real —, e essa lista de exclusão agora vive em um único lugar (content_area.TEXT_EXCLUDED_TAGS), compartilhada pelos dois extratores de texto, em vez de duas cópias que já tinham saído de sincronia.CorrigidoFuncionaMantém os tokens
relcompletos de um link, seu atributotargete seu href bruto, eextrai formulários (#125).
Mantém os tokens
relcompletos de um link, seu atributotargete seu href bruto (anterior à resolução), e extrai elementos<form>— método, action e se há campo de senha (#125). Seis issues catalogadas dependiam desses três fatos que estavam sendo descartados: links cross-origin inseguros (target="_blank"semrel="noopener"/"noreferrer"), links protocol-relative (//host/path, antes da resolução), outlinks para localhost, uma página que recebe ao mesmo tempo um link interno seguido e um nofollow, uma action de formulário insegura e um formulário de senha servido de uma página HTTP sem criptografia. Todas agora correspondem aUNSAFE_CROSS_ORIGIN_LINK,PROTOCOL_RELATIVE_LINK,OUTLINK_TO_LOCALHOST,FOLLOW_AND_NOFOLLOW_INLINKS,FORM_URL_INSECUREeFORM_ON_HTTP_URLno registro. As verificações de formulário, localhost e mistura de nofollow precisam apenas de campos que todo rastreamento já registrava, então essas quatro rodam incondicionalmente; o par cross-origin e protocol-relative precisa delink_attributes.capture, desligado por padrão, porque os dados extras por aresta cresceram cerca de +50% em um rastreamento sintético de 3.387 páginas com 150 links por página — cerca de +95 bytes por aresta, +46 MiB no total, sendo queraw_hrefsozinho responde pela maior parte disso. O registro passa de 121 para 127 verificações.CorrigidoFuncionaCorrige o
report-buildque renderizava em silêncio um relatório sem problemas para o SFAnalyzer…
Corrige o
report-buildque renderizava em silêncio um relatório sem problemas para umaudit.jsondo SF Analyzer (#151). A receita documentada —sf run --tasksencadeado comreport-build --format docx/xlsx/csv/md— lia as chavesfindingse páginas planas, que o schema do SF não usa (os problemas ficam emissues, e os fatos das páginas empages[].metrics); a incompatibilidade produzia um resumo0/0/0/0confiante para uma auditoria que tinha encontrado problemas críticos reais, sem nenhuma seção de problemas.build_reportagora reconhece tanto o formato nativoseohead.site-audit/1quanto o formato do SF Analyzer, normalizando este último para o contrato plano que os quatro escritores voltados ao leitor já entendem, antes de renderizar.--format jsonnão foi tocado — ele já repassava o documento original corretamente, o que provou que os dados nunca estiveram ausentes. Um documento que não bate com nenhum dos dois contratos é recusado comok: False, informando o erro de schema, em vez de ser renderizado como um entregável vazio, e o condicional mortoif ... : passque parecia fazer essa validação mas nunca fazia nada foi removido.tests/test_docs_commands_execute.pyagora confere o resumo renderizado da receita documentada com os totais do próprioaudit.json, e não apenas o código de saída.AlteradoFuncionaFecha duas lacunas de segurança financeira em
seohead/data_sources/(#157, #159).O
geo_guardverificava apenas a string consultivacountry, entãosearch_volume/keyword_ideas/keyword_difficulty/serpainda podiam chegar ao endpoint ao vivo do DataForSEO comlocation_code=2643(Rússia) ou2112(Bielorrússia) sempre que quem chamava informasse o código numérico do alvo geográfico sem preencher tambémcountry; a guarda agora verificalocation_codeprimeiro, pois é esse o campo que de fato é cobrado. Além disso, uma exceção de rede (URLError/TimeoutError/SSLError) durante uma chamada cobrada — opostdo DataForSEO, o/setdo Arsenkin ewordstat.topRequests/wordstat.dynamics/web.searchAsyncdo Yandex Cloud — costumava repetir o mesmo payload sem chave de idempotência, registrando apenas a tentativa que finalmente devolveu uma resposta. Nenhum dos três provedores oferece mecanismo de idempotência para esses endpoints, então uma resposta perdida não é mais repetida: a tentativa é registrada no livro de gastos (custo desconhecido, marcada comoattempt_failed: network_error) e a chamada falha de vez, em vez de arriscar uma segunda cobrança. Leituras idempotentes (/checke/getdo Arsenkin, polling de operações do Yandex Cloud) não foram afetadas e continuam repetindo.yandex_cloud.WebSearch.search_batchisola a submissão perdida à própria consulta, em vez de abortar o lote inteiro.metrika.pyrepete erros de rede da mesma forma, mas não é cobrado em dinheiro e não foi alterado; fica sinalizado para um acompanhamento caso a criação de exportação do Logs API deva receber o mesmo tratamento por motivo de cota.AlteradoFuncionaFecha uma brecha de DNS rebinding em
http_client()(#142):pinned_target(), acorreção da…
Fecha uma brecha de DNS rebinding em
http_client()(#142):pinned_target(), a correção para a janela de TOCTOU descrita em #14, protegia apenas o fetch em modo lista decollect.py— os outros quatorze pontos de chamada, incluindo o motor decrawl-sitedospider.py, deixavam o httpx resolver o DNS uma segunda vez, de forma independente, para abrir o socket. Assim, um resolvedor hostil que respondesse a essa segunda consulta de modo diferente da consulta da própria guarda podia alcançar169.254.169.254ou qualquer endereço RFC 1918, independentemente do veredito da guarda.http_client()agora monta todos os clientes sobre um transporte que fixa a conexão ao endereço que ele mesmo resolve — na primeira requisição e em cada salto de redirecionamento —, mantendo o hostname apenas para o cabeçalhoHoste para o SNI do TLS. A correção é, portanto, estrutural, e não uma disciplina que cada chamador precisasse lembrar.SEOHEAD_ALLOW_PRIVATE_NETWORKS/SEOHEAD_ALLOW_PRIVATE_HOSTScontinuam inalterados.CorrigidoFuncionaCorrige o contrato de código de saída da CLI/MCP para falhas reportadas pelo próprio
handler, e completa…
Corrige o contrato de código de saída da CLI/MCP para uma falha que o próprio handler reporta, e completa
SOURCE_FLAGS(#155, #156). Um handler que devolvia{"ok": false, ...}— a forma documentada pela camada de ferramentas de reportar uma falha de busca, parse ou provedor sem lançar exceção — imprimia esse JSON e saía com 0 na CLI, e devolvia um resultado normal (semisError) pelo MCP, então uma pipeline que dependesse de$?ou um cliente que checasse apenasisErrornão conseguiam detectar a falha.cli.pyagora sai com 1 nesse caso (o código 2 próprio dolog-scanpara uma execução que se contradiz continua sendo um sinal separado e documentado — verdocs/USAGE.md), emcp_server.pylevantaToolErrora partir de um wrapper compartilhado_checked(), para que o cliente vejaisError. Ambos chamam um únicohandlers.handler_failed(), para que as duas interfaces não divirjam sobre o que conta como falha. Além disso,SOURCE_FLAGSganhou--phrase,--keywords,--query/--queries,--seed,--countere--before/--after— cada uma já identifica a entrada inteira de um comando do mesmo modo que--url, mas estava faltando, então um laço por linha sobre qualquer uma delas processava em silêncio apenas a primeira linha. O conjunto agora é construído por_source_flag()no ponto em que cada flag é declarada, em vez de listado à mão em separado, para que não possa sair de sincronia de novo.AlteradoFuncionaExpande
docs/scenarios/de dez cadeias para cinquenta e seis, agrupadas pela perguntado leitor…
Expande
docs/scenarios/de dez cadeias para cinquenta e seis, agrupadas pela pergunta com que o leitor chega (#120). Quais cenários existem é decidido pelo mapa de cobertura, e não pelo gosto: cada um declara as issues catalogadas que resolve, etests/test_scenario_coverage.pyafirma que toda issue que este toolkit diz encontrar aparece em pelo menos um cenário, que nenhum cenário cita uma issue que o mapa não lista e que nenhum deixa de fora suas limitações. Todas as 143 issues encontráveis estão cobertas. Cada comando de cada arquivo continua sendo executado contra o site de teste no CI — a suíte roda 2.008 testes, dos quais o gate de comandos de documentação é agora o maior grupo isolado.AlteradoFuncionaAfirma os próprios limites do protocolo de sitemap (#124):
SITEMAP_TOO_MANY_URLSacimade 50.000…
Afirma os próprios limites do protocolo de sitemap (#124):
SITEMAP_TOO_MANY_URLSpara mais de 50.000 entradas em um único arquivo,SITEMAP_TOO_LARGEpara mais de 50 MB sem compactação, eSITEMAP_URL_DUPLICATEDpara uma URL declarada em mais de um sitemap, nomeando os dois documentos. Um arquivo que ultrapassa qualquer um dos limites é inválido, não apenas grande — um mecanismo de busca pode ler parte dele e descartar o resto sem que o dono do site veja nada —, e os limiares vêm do protocolo, não da configuração. Os dois parsers agora registram o tamanho em bytes e a contagem declarada de cada documento, e os problemas nomeiam o sitemap filho, não o índice. O registro passa de 118 para 121 verificações.AdicionadoFuncionaAdiciona
docs/GUIDELINE.md, o documento que a pessoa lê primeiro (#121).Adiciona
docs/GUIDELINE.md, o documento que a pessoa lê primeiro (#121): o que esta ferramenta é e o que não é, uma primeira execução de ponta a ponta, como escolher a taxa de rastreamento e como saber se os erros são seus, como ler oaudit.jsonsem ser induzido ao erro por ele, o que o arquivo de configuração muda e o que apenas custa, os seis erros que todo mundo comete no início, o que fazer quando a ferramenta está errada e o que ela não consegue responder de jeito nenhum. Linkado logo no início do README, antes da referência.AdicionadoFuncionaAdiciona
docs/COVERAGE_SF_ISSUES.md, gerado a partir deseohead/sf/core/sf_issue_map.py.Adiciona
docs/COVERAGE_SF_ISSUES.md, gerado a partir deseohead/sf/core/sf_issue_map.py: cada uma das 320 issues do catálogo publicado da área, cada uma com exatamente um status — encontrada por uma verificação nomeada, encontrada por um comando nomeado, encontrada em parte com a parte faltante declarada, uma lacuna nomeada, ou uma decisão com seu motivo (#119). Das 212 issues dentro do escopo, 126 são encontradas hoje e 17 em parte; 41 são lacunas e 28 exigem algo deliberadamente não construído. Acessibilidade (92) e AMP (16) foram recusadas como decisões únicas, com as listas completas exibidas para que a decisão seja auditável. Um teste garante que cada ID de verificação e cada comando referenciado ainda existem, de modo que uma renomeação quebre o build, e não o documento. Substituidocs/CHECKLIST_AUDIT.md, que foi escrito sem o catálogo em mãos.AlteradoFuncionaO seeder de sitemap solicita o endereço como o sitemap o publicou, e não a forma
normalizada.
O seeder de sitemap solicita o endereço como o sitemap o publicou, e não sua forma normalizada (#115).
sitemap.crawl()devolvia apenas olocnormalizado, então um sitemap que declarava/a/provocava a busca de/a— na maioria dos CMSs, um 301 que o crawler inventava e depois reportava como fato sobre o site, e um 404 onde a forma sem barra final nem é roteada. Cada entrada agora traz oloccomo publicado, junto comloc_normalizedpara os consumidores que comparam por ele. Estatísticas de redirecionamento de rastreamentos anteriores semeados pelo sitemap são suspeitas por esse motivo.AlteradoFuncionaReestrutura a skill de operador em um diretório controlador (#111).
.claude/skills/agora tem dois níveis: 21 skills de método, cada uma cobrindo uma coisa bem, econtrol/, que decide quais delas rodar em um site que ninguém ainda analisou. O controlador roteia em vez de repetir o conteúdo, e traz cinco sub-skills carregáveis (escopo, taxa e carga, leitura de uma auditoria, verificação e entregáveis) e um arquivo de referência com três partes (defeitos encontrados em sites no ar e o que revelou cada um, qual população cada verificação descreve e o que o toolkit não consegue responder de jeito nenhum). Os gates somente em inglês e de comandos de documentação agora cobrem todo arquivo Markdown sob um diretório de skill, e não apenasSKILL.md.AdicionadoFuncionaAdiciona
tests/chains/: um site de teste montado com as formas que de fato quebramcadeias de rastreamento.
Adiciona
tests/chains/: um site de teste montado com as formas que de fato quebram cadeias — as duas formas com e sem barra final de uma mesma URL, um corpo que não é UTF-8 válido, uma página em windows-1251, um cabeçalho do site fora de<main>, um link para fora do host, um caminho bloqueado pelo robots.txt —, rastreado em loopback, com dezessete afirmações sobre a execução como um todo, e não sobre um módulo isolado (#112). Quatro propriedades: conservação (um número não muda de significado enquanto percorre o sistema), população (um problema é sobre um membro do conjunto que ele descreve), determinismo (dois rastreamentos, dois níveis de concorrência, uma resposta) e representação (uma página diz como foi medida). As regras de população são as do própriologscan, então uma contradição que o scanner consegue nomear é uma afirmação de teste de cadeia.AlteradoFunciona
reconcile_sitemapinforma cada URL como foi escrita, e não como foi normalizada.A comparação continua acontecendo pela chave normalizada, mas um problema que citava uma forma normalizada citava uma URL que não aparecia em lugar nenhum do rastreamento — inútil para quem lê e indistinguível, para o scanner de anomalias, de um problema sobre uma página que nunca foi buscada.
AdicionadoFuncionaAdiciona
docs/scenarios/: dez cadeias de ponta a ponta, cada uma com os comandos reaisem ordem, o artefato resultante, o custo e aquilo que a cadeia não consegue responder (#110). O restante da documentação lista o que o toolkit tem; isto descreve o que ele faz. Linkado no README, acima da lista de ferramentas, para que um agente que avalie o repositório encontre as cadeias antes do inventário. Cada comando exibido é executado contra o site de teste por
tests/test_docs_commands_execute.py, cujos extrator e gates de inglês e de contagem agora percorremdocs/em todos os níveis, e não apenas no topo.AdicionadoFuncionaAdiciona
log-scan(CLI) eseo_log_scan(MCP): lê os artefatos de uma execuçãoconcluída e aponta…
Adiciona
log-scan(CLI) eseo_log_scan(MCP): lê os próprios artefatos de uma execução concluída e reporta afirmações que não podem ser verdadeiras ao mesmo tempo (#109). Oito regras, cada uma escrita a partir de um defeito que passou por toda a suíte de testes — um tamanho registrado que discorda do arquivo em disco, uma proporção de texto acima de 100%, uma verificação disparando mais vezes do que há páginas para disparar, um problema sobre uma URL que a execução nunca buscou, uma tag canonical tratada como redirecionamento enquanto aquela URL respondia 2xx na mesma execução, um resumo que discorda das próprias linhas, palavras contadas em uma página de zero byte e páginas medidas de duas formas em que só algumas dizem qual delas. Cada anomalia nomeia os dois valores e de onde cada um foi lido. A CLI sai com código 2 quando uma execução se contradiz, para que uma pipeline pare em vez de publicar os números.AlteradoFuncionaO teste de pacing entre workers não mede mais o relógio de parede (#107).
_DispatchGateagora lê o relógio injetado do rastreamento em vez de chamartime.monotonic()diretamente, então o teste conduz o gate com um relógio virtual que avança somente quando algo dorme: os instantes de despacho são a aritmética do próprio rastreador, e a afirmação é exata. A forma antiga comparava intervalos reais decorridos com um piso de 0,024 s e falhava em código inalterado sempre que a máquina estava ocupada.AlteradoFuncionaFecha a segunda metade da auditoria de configurações não conectadas (#91).
http.headersé mesclado a todas as requisições junto dos cabeçalhos de credencial;speed.adaptivecontrola o atraso do throttle e o ajuste de concorrência (os contadores de timeout e de erro de servidor continuam rodando — desistir é um mecanismo separado de recuar);discovery.hyperlinks.store/.crawl,discovery.external.storeediscovery.redirects.crawlagora decidem o que o rastreamento registra e o que ele segue.discovery.canonicals.*,discovery.external.crawlediscovery.redirects.storeforam removidos em vez de conectados: nomeavam capacidades que o spider não tem (seguir canonicals, rastrear entre hosts) ou um estado que não consegue reter, e uma configuração que aparece em--config-helpe no manifesto da execução sem mudar nada é pior do que nenhuma configuração. O conjunto de exceções do canário de cobertura está agora vazio: cada caminho deDEFAULTSaltera um resultado observável e é nomeado por um teste.AlteradoFuncionaDetectar a área de conteúdo pela semântica do próprio documento quando nada estiver
configurado…
Detecta a área de conteúdo pela semântica do próprio documento quando nada está configurado (#96): primeiro
main, depois[role="main"], depoisarticle, registrando qual deles casou comoauto_main/auto_role_main/auto_article. O padrão anterior — o body inteiro menos as tagsnavefooter— contava 126 palavras de template em 433 numa postagem real do WordPress (29%), incluindo um link de “pular para o conteúdo”, e essa inflação alimentavaTHIN_CONTENTeLOW_TEXT_RATIOna mesma direção em todas as páginas de um template.headereasidepassam a somar-se anavefooteremDEFAULT_EXCLUDE_TAGSno caminho de fallback. Um seletor configurado continua tendo prioridade, e um seletor que não encontra nada ainda cai emfallback_default_body, em vez de detectar silenciosamente outra região.AlteradoFunciona
URL_NOT_IN_SITEMAPagora compara páginas com páginas (#94).Comparava as URLs de um sitemap com todos os destinos do grafo de links do rastreamento. Num site real de 124 páginas, disparava 392 vezes: 362 arquivos de imagem que uma galeria linka diretamente, cinco links para outros hosts e 30 URLs que o rastreamento nunca acessou. Isso representava 74% do relatório e enterrava os achados que eram reais. Agora o lado observado são as páginas que o sitemap deveria declarar: coletadas, com resposta 2xx, em HTML, do mesmo host e indexáveis.
reconcile_sitemaprecebe essa população como um argumentocomparableseparado, entãoSITEMAP_ORPHANcontinua verificando a acessibilidade contra todos os destinos de link e não pode inventar órfãos. O que ficou de fora é devolvido emlinked_not_comparable, e não descartado.CorrigidoFuncionaCorrige as verificações de canonical em sites que servem as duas formas da URL, com e sem
barra final (#95).
norm_urlelimina a barra final de propósito, para que um canonical escrito sem ela case com a página que a tem. Mas o índice normalizado guardava só uma página por chave, e um rastreamento de um site típico de WordPress tem duas:/x(301) e/x/(200). Ler a que foi inserida primeiro faziaCANONICAL_TO_REDIRECTapontar 78 páginas ativas cujo canonical responde 200.AuditContextagora expõepages_by_norm, com todas as páginas de cada chave;page_by_normdevolve a variante que respondeu 2xx; eCANONICAL_TO_REDIRECTeCANONICAL_NON_INDEXABLEsó disparam quando nenhuma variante os contradiz.CorrigidoFuncionaCorrige
size_bytes: agora é o corpo da resposta como chegou pela rede, medido antes dadecodificação…
Corrige
size_bytes: agora é o corpo da resposta como chegou pela rede, medido antes de o corpo ser decodificado (#99). Antes era medido a partir da string já decodificada, então cada byte que não era UTF-8 válido virava U+FFFD e era recodificado em três bytes. Um WebP de 739 KB de um rastreamento real foi registrado como 1,27 MB, e o fator de inflação variava de arquivo para arquivo. Imagens, PDFs, fontes e HTML servidos em charset legado (windows-1251) estavam todos superdimensionados, e assim também a razão de texto calculada com esse denominador. O cache HTTP guarda o tamanho da rede junto com a entrada, então uma página reproduzida informa o mesmo que a busca ao vivo informou. O schema passa parahttp_cache.v2, e entradas v1 são buscadas de novo uma vez, em vez de reproduzidas sem tamanho.AdicionadoFuncionaAdiciona
docs/TOOL_REFERENCE.md, gerado a partir das definições de ferramentas MCP(
seohead/mcp/tool_reference.py,scripts/generate_tool_reference.py): os argumentos de cada ferramentaseo_*/sf_*, com tipo e padrão, seu custo (rede, escritas, idempotência, gasto, lido do perfilToolAnnotations) e as notas de comportamento e de falha da própria docstring.tests/test_docs_drift.pyfalha o build se o documento divergir das definições ou se faltar alguma ferramenta.AdicionadoFuncionaAdiciona
tests/test_docs_commands_execute.py: extrai cada comandoseohead ...mostrado em README/docs/skills/exemplos…
Adiciona
tests/test_docs_commands_execute.py: extrai cada comandoseohead ...mostrado em README, docs, skills e exemplos (scripts/doc_commands.py) e executa cada um offline, contra um site de fixture em loopback (tests/doc_fixtures/) e cópias materializadas deexamples/, verificando saída limpa. Comandos que exigem infraestrutura real (RDAP/DNS, binário licenciado do SF, credencial de provedor pago, o servidormcp, que nunca retorna) são ao menos analisados pelo parser de argumentos ativo. Um comando documentado que deixa de funcionar agora falha no CI, em vez de ser publicado desatualizado.AlteradoFuncionaReorganiza as 21 skills técnicas de fluxo de trabalho (
.claude/skills/*/SKILL.md) em umformato comum: Gatilho, Anti-gatilho, Pré-condições (como checklist), o Fluxo de trabalho existente, Pontos de decisão, Definição de pronto (como checklist) e Custo. Corrige a contagem desatualizada de cobertura de comandos no fim de
docs/SKILLS.md. A contagem real, recalculada escaneando todos os arquivos de skill, passa a ser verificada por um novo teste de drift.CorrigidoFuncionaCorrige várias contagens de ferramentas e testes que tinham divergido silenciosamente dos
registros reais: a contagem de comandos da CLI em
docs/USAGE.md,docs/COMPARISON.md,README.mdedocs/TESTING.md; a contagem de ferramentas MCP emdocs/TOOLS.md; a contagem da referência de ferramentas emdocs/README.md; e a contagem de testes offline. As corrigidas são fixadas com um teste de regressão (test_stale_tool_counts_do_not_reappear).AdicionadoFuncionaAdiciona as quatro auditorias estáticas do Lighthouse que não precisam de navegador nem
de API de terceiros (#59):
MISSING_CHARSET,MISSING_DOCTYPE,VIEWPORT_MISSINGeNO_COMPRESSION, cada uma calculada a partir de evidências que um rastreamento já possui.content_encoding,meta_charset,doctypeeviewportentram no vocabulário normalizado de colunas. Assim, uma exportação do SF que traga esses dados como colunas de Custom Extraction alimenta as mesmas verificações. O registro passa de 114 para 118 verificações.AlteradoFuncionaConecta as dez configurações restantes do rastreador, que eram validadas e gravadas no
manifesto da execução e descritas por
--config-help, mas não eram lidas por nada (#63).limits.max_response_bytes,speed.max_delay_seconds,robots.user_agent_tokenespeed.stop_after_consecutive_timeoutsagora configuram um comportamento que antes era fixo no código.robots.unavailable_means_stopagora define se um robots.txt inacessível ou com erro 5xx interrompe o rastreamento ou é tratado como sem restrições. Antes, um robots.txt inacessível nunca interrompia o rastreamento, independentemente da política, enquanto um 5xx sempre interrompia. Agora os dois são o mesmo caso “indisponível”, controlado pela configuração.limits.max_url_length,limits.max_query_variants_per_path,http.retry_on_timeoutediscovery.follow_nofollowsão comportamentos implementados agora.http.user_agentpassa a ser aplicado às requisições reais, em vez de sempre enviar o padrão da ferramenta. Adicionacrawl-describe-settings(CLI) eseo_crawl_describe_settings(MCP), para que um agente descubra a superfície de configuração sem acesso ao sistema de arquivos (#23).AdicionadoFuncionaAdiciona busca personalizada (
tools/custom_search.py) e extração personalizada(
tools/custom_extract.py) sobre um corpus já rastreado: filtros de presença e ausência (código-fonte bruto, texto visível, um elemento CSS nomeado ou um nó XPath) e extratores CSS/XPath/regex. Ambos informam contra qual representação rodaram: marcação estática ou DOM renderizado. A ausência é contada com honestidade: uma página cuja busca falhou fica fora do numerador e do denominador, em vez de ser contada como ausente. A extração roda cada par (documento, extrator) sob um orçamento de tempo real (SIGALRMem POSIX). Uma expressão patológica aborta só aquele documento, e a execução termina mesmo assim.AdicionadoFuncionaAdiciona a classificação de posição dos links (
tools/link_position.py): nav, header,sidebar, footer ou conteúdo, por regra ordenada sobre o caminho de ancestrais de cada link. Reaproveita a noção de conteúdo de
content_area.py, em vez de criar uma segunda. Está conectada ao registro de links decrawl/spider.pyatrás delink_position.classify(desligada por padrão, pois guardar uma posição por link custa memória num rastreamento grande). É agregada no site inteiro porinlink_compositiondecrawl/linkgraph.py, que agora alimenta o novo achado de auditoriaINLINK_BOILERPLATE_ONLY, para páginas linkadas apenas a partir de trechos de template. O registro passa de 104 para 105 verificações.AdicionadoFuncionaAdiciona oito cálculos de segunda passagem pós-rastreamento, que só podem ser respondidos
depois que o rastreamento termina (issue #15): uma pontuação de link interno calculada a partir do grafo de arestas
all_inlinks(LOW_LINK_SCORE); um alvo de canonical para o qual nenhum hiperlink aponta (UNLINKED_CANONICAL); detecção de loop emrel="next"e de séries sem links (PAGINATION_LOOP,UNLINKED_PAGINATION_SERIES); reciprocidade de hreflang (HREFLANG_MISSING_RETURN_LINK); agregados de composição de inlinks (ONLY_NOFOLLOW_INLINKS,ONLY_NONINDEXABLE_SOURCE_INLINKS); o caminho de descoberta mais curto a partir da semente do rastreamento (DEEP_DISCOVERY_PATH); um fallback de conteúdo misto calculado pela própria ferramenta (INSECURE_SUBRESOURCE); e agrupamento de quase-duplicatas a partir do texto armazenado das páginas (NEAR_DUPLICATE/DUPLICATE_BY_HASH), conectandotools/duplicate.pyetools/content_area.pyà auditoria pela primeira vez.ORPHAN_PAGE,SITEMAP_ORPHANe as duas novas verificações de “sem links” agora são retidas: aparecem como um pulo nomeado, e não como achado, em um rastreamento que o agregador marcou como parcial, já que “nada linka para cá” não pode ser comprovado num rastreamento truncado. O registro passa de 104 para 114 verificações.AlteradoFuncionaAudita o registro do rastreador contra uma checklist externa de SEO técnico e fecha oito
lacunas baratas e comprovadas: cinco verificações de hreflang (códigos de idioma e região inválidos, autorreferência ausente, x-default ausente, entradas duplicadas e destinos não canônicos), duas diretivas de robots (
notranslate,unavailable_after) e URLs canônicas com fragmento. O registro passa de 96 para 104 verificações. Vejadocs/CHECKLIST_AUDIT.md.AdicionadoFuncionaAdiciona
asset-weight-check: busca os CSS e JS linkados de uma página e informarecursos que bloqueiam a renderização, arquivos grandes demais, bibliotecas duplicadas (por hash de conteúdo), falta de minificação, falta de
font-display, JS legado com polyfill e falta de compressão e de cache de longa duração.AdicionadoFuncionaAdiciona
crawl-site --sitemap <url>(esitemaps.auto_discoverem--config): semeiao rastreador nativo com as URLs declaradas no sitemap, segue os links de cada uma e reconcilia os conjuntos declarado e observado em
summary.sitemapdoaudit.json, sob os mesmos IDs de verificaçãoSITEMAP_ORPHAN/URL_NOT_IN_SITEMAPque o pipeline do Screaming Frog já reporta.AdicionadoFuncionaAdiciona
crawl-site --config-help, gerado a partir deseohead/crawl/config.py, eoculta
--max-depthe--min-delaydo--help(continuam aceitos), para que a superfície de flags pare de crescer a cada configuração do rastreador.AlteradoFuncionaSepara a identificação de tecnologias em uma etapa de busca e uma etapa pura
analyze_tech. Captura os IDs de analytics e de gerenciador de tags, em vez de apenas os nomes, e adiciona um relatóriotag_coverage, que agrupa a presença por template de URL e registra como cada página foi medida.AlteradoFuncionaResolve cadeias e loops de redirecionamento como uma segunda passagem sobre os destinos
de redirect de um rastreamento concluído…
Resolve cadeias e loops de redirecionamento como uma segunda passagem sobre os próprios destinos de redirect de um rastreamento concluído. Assim,
REDIRECT_CHAIN/REDIRECT_LOOPnão dependem mais do relatório nativo Redirect Chains do Screaming Frog. Uma exportação em perfil light ou uma execução decrawl-sitegera os mesmos achados, sem nenhum passo extra.AdicionadoFuncionaAdiciona uma área de conteúdo configurável (
content_area.py) que limita a contagem depalavras à região principal, excluindo navegação e rodapé por padrão, sem afetar a descoberta de links. A estratégia resolvida é informada por página.
AlteradoFuncionaSepara duplicatas exatas de quase-duplicatas em
duplicate.py: correspondências exatasrecebem hash do texto…
Separa duplicatas exatas de quase-duplicatas em
duplicate.py: as exatas recebem hash a partir do texto extraído (e não dos bytes brutos) e ficam fora dos agrupamentos de quase-duplicatas. As comparações consideram, por padrão, só páginas indexáveis.AdicionadoFuncionaAdiciona um relatório de consistência de boilerplate (
boilerplate_report.py) quecalcula hash de header, nav e footer…
Adiciona um relatório de consistência de boilerplate (
boilerplate_report.py) que calcula o hash de header, nav e footer por página e sinaliza os grupos de template minoritários.AdicionadoFuncionaAdiciona extração de Markdown sem dependências (
markdown_extract.py): renderização sóda área de conteúdo…
Adiciona extração de Markdown sem dependências (
markdown_extract.py): uma renderização só da área de conteúdo e outra do documento completo.AlteradoFuncionaConecta
markdown_extracteboilerplate_reportà CLI e à superfície MCP comomarkdown-extract/seo_markdown_extracteboilerplate-report/seo_boilerplate_report(47 ferramentas centrais, eram 45). Também adiciona a flagonly_indexable, queduplicate_checkjá tinha na camada de handler, à assinatura MCP deseo_duplicate_check, onde ela havia sido esquecida. O caminho por URL docitability-checkdeixa de usar o campotextdo parser, que é o documento inteiro colapsado numa linha, sem quebras de parágrafo nem de título, e passa a usar o Markdown da área de conteúdo demarkdown_extract. Isso corrige tanto a diluição por boilerplate levantada na issue quanto um bug antigo: o texto simples zerava silenciosamente as dimensões Answer-Blocks e Structure-Quality em todas as URLs ativas. Ficou sem escopo de propósito o próprio campotextdo parser, que continua sendo do documento inteiro. Motivo: a extração de evidências de schema empage_facts.py(linkssameAsde redes sociais, breadcrumbs, regex de preço e avaliação) depende de fatos que de fato ficam em widgets de header e footer, que a área de conteúdo exclui. Também ficaram de fora as verificaçõesTHIN_CONTENT/LOW_TEXT_RATIOguiadas pelo Screaming Frog, emsf/core/rules.py, cujosword_count/text_ratiovêm das colunas de exportação do próprio Screaming Frog. São dados de terceiros, e o toolkit não tem o HTML bruto para reescopar sem re-buscar cada página, o que anularia o desenho de corpus offline sem requisições do caminho de auditoria SF. O rastreador próprio do toolkit (crawl-site) já herda o escopo da área de conteúdo de graça, pois sua contagem de palavras lê direto deparser.parse_html.AlteradoFuncionaDocumenta uma convenção de nomes (
docs/NAMING.md) e resolve as colisões de nome-base demódulos e os arquivos de teste nomeados por processo que ela encontrou. Nenhum nome de comando da CLI, handler ou ferramenta MCP mudou.
- AdicionadoFuncionaAdiciona arquivos de integração para comunidade, citação e agentes que não usam chave.
AdicionadoFuncionaAdiciona a skill de fluxo de trabalho com permissão
analytics-console-reviewe trêsreceitas práticas.
- AlteradoFuncionaDocumenta o suporte à linha de segurança atual
3.x. AlteradoFuncionaExige TLS 1.2 ou superior e fixa as sondagens diretas de certificado em endereços
públicos previamente validados.
AdicionadoFuncionaAdiciona um cache de respostas HTTP para
crawl-site(seohead/crawl/cache.py, ativadopor
cache.mode, com padrãooff, para que nenhum efeito colateral apareça por padrão). Traz semântica real de frescor HTTP:max-age/Expires, revalidação porETag/Last-Modified, variantes sensíveis aVary, e respeito ano-store/no-cache. Há um modoreplaypara depuração, registrado no manifesto e nunca como padrão, e uma flaginvalidatepara um recarregamento forçado explícito. Cada página buscada trazcache_status(hit/revalidated/miss). A execução trazcache_statsecache_replay, tanto na saída do handler quanto no blocorundoaudit.json, então um relatório montado em parte a partir do cache informa isso. Um acerto de cache não gera requisição e também não consome atraso de throttle nem vaga do portão de despacho concorrente. A espera é emitida dentro do própriofetch_one, só quando uma ida e volta real pela rede está prestes a acontecer.AdicionadoFuncionaAdiciona reuso orientado pelo diário em
seohead/core/runlog.py(SEOHEAD_REUSE_POLICY,idade máxima por ferramenta em segundos; padrão vazio, ou seja, nada é reutilizado). Uma resposta anterior bem-sucedida, configurada e ainda dentro do prazo, é devolvida em vez de chamar a ferramenta de novo. Ela vem marcada com
reused: trueereused_from_ts, tanto no resultado quanto na nova entrada do diário, que continua sendo gravada. O frescor é sempre medido a partir de quando o valor foi de fato buscado, e nunca é estendido pelo próprio reuso.
Roteiro
108 abertasData = o dia em que a mudança chegou (data git do fragmento changelog.d/). Número = a issue que fecha. Título = primeira frase, detalhes ao clicar.