Registro de cambios
Qué ha cambiado en SpiderHead, versión a versión. Cada entrada indica qué tipo de cambio es y si funciona hoy.
Unreleased
Desde 3.1.065 entradas22 de octubre de 2026
7 cambiado2 corregidoCambiadoFuncionaA results difference between two scans can now be attributed.#1529
The new read-only
#1529 (incidencia en GitHub)scan-config-diff(CLIseohead scan-config-diff --before a.sqlite --after b.sqlite, MCPseo_scan_config_diff) reads both scans' recorded effective configurations from their headers — the sites are never re-read — and reports a field-by-field diff over the manifest's dotted setting paths: changed settings with both values, added, removed, an identical flag, and how many settings were compared. Identical configurations report no differences; a free-form map such ashttp.headerscompares as one leaf, exactly as the manifest records it.CambiadoFuncionaA native crawl now measures its own reading level.#1516
The new
#1516 (incidencia en GitHub)checks.readabilitymodule computes, offline over each page's retained content area, the sentence count, average words per sentence, the Flesch Reading Ease score (206.835 − 1.015·words/sentences − 84.6·syllables/words, English vowel-group syllable heuristic, versionflesch-reading-ease.v1) and the standard band label. The four values are stored as per-URL scan fields (pages.sentence_count,avg_words_per_sentence,flesch,readability), carried into the analyzer frame under the same column names an SF export uses — so the existing READABILITY_DIFFICULT and LONG_SENTENCES checks now fire on native crawls too, with no new check IDs. A page whose content area was not retained, or holds no word with a letter, records NULL/"" — unmeasured, never a zero that would read as measured-and-easy. Text ratio and word count behavior are unchanged.CorregidoFuncionaCrawls on hosts that enforce https no longer spend a redirect hop on every http URL.#1484
The new opt-in
#1484 (incidencia en GitHub)http.upgrade_to_httpssetting rewrites http URLs to https before any request — seed, sitemap seeds and discovered links alike, in both spider and list modes and in native scans: no redirect is recorded for the upgrade, the http and https spellings collapse into one page identity, and each page fetched this way carriestransport_upgraded: truein its record (persisted aspages.transport_upgraded, absent in older scans reads as false). The operator opting in is the declaration that the hosts enforce transport security; a host without https answers with visible connection errors rather than a silent fallback. With the setting off, nothing changes.CambiadoFuncionaA crawl started deep can now stay in its own subtree.#1481
The new
#1481 (incidencia en GitHub)scope.start_folder_onlytoggle admits only URLs at or below the start URL's path folder: a crawl started at/blog/postwalks/blog/and everything under it, and links pointing above the folder are counted as unfollowed evidence (excludedunderoutside_start_folder) exactly like any other scope rejection — no hand-written include patterns required. The folder is the directory the start URL sits in (a trailing-slash start keeps its own folder); a start URL at the host root is refused, because the root has no folder to stay below. The setting is recorded per scan in the run manifest like every result-affecting setting, and appears incrawl-describe-settings. With the toggle off nothing changes.CorregidoFuncionaPages that link at robots-disallowed targets are no longer silent about it.#1486
When robots.txt disallows a linked URL and the crawl's robots policy is
#1486 (incidencia en GitHub)respect, the target is never fetched and never becomes a page row, so no target-side check can see it: the link between a page and a whole hidden section existed only in the edge list. The newROBOTS_BLOCKED_OUTLINKfinding (notice) lists, per source page, the outlinks whose destinations the policy kept out — both URLs named, internal and external edges alike, the target still never fetched. The population follows the robots policy mode: underreport_onlythe same targets are reported (they would have been blocked), and underignorethe check skips honestly — no URL was measured against robots.txt. Crawl-list runs without retained link edges skip by name like the other link findings.CambiadoFuncionaAn image-only link now names its destination when the wrapped image carries alt text.#1518
Links whose visible content is an image used to show an empty anchor in link evidence even when the image had a descriptive
#1518 (incidencia en GitHub)alt, so anchor-text review treated every image link as unnamed. The parser now records that alt as the link's anchor with ananchor_source: "alt"marker distinguishing alt-derived anchors from text-derived ones (absent marker = text or nothing). A link with visible text keeps its text; a link with neither stays empty and keeps feeding the no-anchor-text checks. The marker rides the LinkEdge into the scan (links.anchor_source), the links export and the per-link query views; a scan written before the field reportsnullthere rather than a false text-derived answer.CambiadoFuncionaHrefs that cannot become fetchable link targets leave evidence instead of vanishing.#1530
Link parsing drops an unparsable href (malformed syntax, e.g. a truncated
#1530 (incidencia en GitHub)http://[invalid) or a non-http(s) scheme (mailto:,javascript:) with no trace: the source page keeps nothing to say it points at something broken. The new opt-in crawl settingdiscovery.record_invalid_targetsrecords each rejection per page — the raw href exactly as written plus the reason (unparsable_syntax/unsupported_scheme) — through the parser, the crawl record, the scan schema (pages.invalid_link_targets_json) and the analyzer frame, and the newINVALID_LINK_TARGETcheck turns the pages that have them into findings with the raw values as evidence. A missing href and a pure in-page#anchorare absence, not defects, and are never recorded; a measured clean page records an empty list; a crawl that ran without the setting skips the check honestly instead of reporting a clean site nobody measured. Rejected targets are data: they never enter the frontier. The setting is off by default and is recorded in the run manifest like every finding-changing setting.CambiadoFunciona
HEADING_SKIPnow flags heading-order jumps in both directions, completing the#1545heading-sequence check: a content heading that skips a level down (H2 -> H4) and one that jumps back up past an open section (H4 -> H2) are the same defect -- the outline steps over a section that was never opened or never closed. A one-level return (H3 -> H2) closes the current section and starts a sibling, which is correct nesting and stays clean, matching the SF 24.3
#1545 (incidencia en GitHub)axe.heading_orderbehaviour the check was modelled on. Evidence rows carry from/to levels and texts for both directions.CambiadoFuncionaThird-party product names now appear only where they describe compatibility: a trademark#1554
and non-affiliation notice was added, the export analyzer is called Export Analyzer, and report reasons and docs describe what an export lacks instead of making claims about another product.
#1554 (incidencia en GitHub)
21 de octubre de 2026
3 añadido4 cambiado3 corregidoCambiadoBetaEscritorio: el conjunto de URL como lista plana o como árbol de rutas.#1492
Un conmutador de lista/árbol al final de la barra de grupos cambia el conjunto de datos entre la página plana y un árbol de rutas plegable, construido sobre las mismas filas y filtros: los hosts son los nodos superiores, las URL de directorio son sus propias carpetas-hoja y las URL de documentos cuelgan de la última carpeta. Al elegir una hoja se controla la selección compartida de la tabla, así que los detalles y los filtros se mantienen al cambiar de vista.
#1492 (incidencia en GitHub)AñadidoBetaEscritorio: modo de revisión solo de datos.#1495
View > Data only (Ctrl+Alt+D) oculta la navegación y la barra superior en sesiones largas de revisión y deja solo los datos; la elección se mantiene por sesión, y los paneles de cada pantalla siguen respondiendo a sus propios conmutadores.
#1495 (incidencia en GitHub)CorregidoBetaLogs: aceptan time-taken en cualquier posición y diseños con un solo ident.#1534
Los parsers de Apache ahora extraen referer, user-agent y time-taken cuando el tiempo de respuesta aparece entre el tamaño y el referer o al final de la línea, en lugar de descartar en silencio ambos campos entre comillas. La detección de formato acepta uno o dos tokens ident entre la IP del cliente y la marca de tiempo, así que el formato personalizado de nginx con un solo guion se importa en lugar de fallar por completo. El informe de importación indica las variantes aceptadas (combined-2-ident, combined-1-ident). Cubre #1534 y #1535.
#1534 (incidencia en GitHub)CambiadoBetaEscritorio: la escala de espaciado está terminada, sin márgenes fuera de escala.#1374
Los 184 puntos de llamada restantes de setContentsMargins/setSpacing fuera de escala, repartidos en 60 archivos, pasan a la escala de tokens con una asignación que solo reduce, y el test de trinquete ahora falla ante cualquier valor fuera de escala. Antes se normalizaron Search, images, inbox, issues, logs, journal y onboarding.
#1374 (incidencia en GitHub)CambiadoBetaEscritorio: mejoras rápidas, valores TSV sin formato, proyecto en el título de la ventana
y texto terciario con contraste AA.
copy_tsv pega los valores almacenados, así que el marcador visible de «sin datos» nunca llega a una hoja de cálculo; el título de la ventana muestra el proyecto abierto (Project — SpiderHead); el texto terciario ahora cumple el contraste AA sobre superficies elevadas.
CorregidoBetaEscritorio: regiones de teclado coherentes, Return para abrir detalles y errores de
lectura legibles.
F6 recorre solo la navegación y la página actual; Return abre los detalles de la fila seleccionada, como prometía siempre el menú de la fila; los errores de lectura en la barra de estado indican la operación (tabla de URL, parámetros de rastreo) en lugar del identificador de solicitud sin procesar.
CambiadoBetaEscritorio: el menú View se vincula a los paneles propios de la pantalla actual.
Una pantalla puede exponer panel_actions(), tríos (título, si está visible, alternar), y el menú View construye su sección de paneles a partir de la pantalla al mostrarla. La pantalla de URL ofrece su resumen de ejecución y el modo solo tabla; los elementos de auditoría heredados siguen en su propia página.
CorregidoBetaEscritorio: que los ticks de actividad dejen de llenar los logs de ventanas cerradas.
La señal global de actividad seguía llamando a widgets BusyIndicator ya eliminados; las ventanas cerradas ahora permanecen en silencio.
AñadidoBetaEscritorio: las pestañas del modo simple se pueden ocultar y restaurar.
Menú contextual de la barra de pestañas: ocultar una pestaña, restaurar las ocultas o mostrarlas todas; la elección se mantiene. La primera pestaña siempre permanece, la última pestaña visible no se puede ocultar y una pestaña oculta reaparece cuando Overview entra en ella.
AñadidoBetaEscritorio: estados del modo simple, barra de marca y capturas sin conexión.
Paneles de estado con acciones: sin resultados (borrar búsqueda / mostrar todo), fallido (reintentar / mostrar registro), núcleo no encontrado (abrir ajustes); un aviso de detención cuenta las URL rastreadas y en cola. La barra de herramientas lleva la marca de la araña, y el contador de errores es una insignia.
20 de octubre de 2026
1 añadido3 cambiadoCambiadoBetaEl paquete de la CLI
seoheadse divide en módulos por dominio.#1514
#1514 (incidencia en GitHub)cli/_shared.pycontiene los registros de comandos y los auxiliares de entrada;checks_cmds,project_cmds,scan_cmds,crawl_cmds,sources_cmds,reports_cmdsymisc_cmdscontienen cada uno su parte del antiguo mapeo de argumentos con nombre (kwarg), de las banderas de argparse y de los casos especiales del despacho principal decli/__init__.py. La superficie de importación publicada no cambia y el módulo se reduce de 4506 a 513 líneas; la salida de--helpsigue siendo idéntica byte a byte para cada comando.CambiadoBetaLos manejadores de MCP pasan a un paquete propio.#1514
Los manejadores del servidor ahora viven en
#1514 (incidencia en GitHub)seohead/mcp/handlers/, divididos por dominio: proyectos, tráfico, logs, fuentes, contenido, semántica, flujo de trabajo, escaneos conservados, evidencias y exportación BI, entorno y catálogo. La documentación y las referencias a rutas de código siguen la nueva estructura.CambiadoBetaTabla de URL: selección de varias filas con copia TSV de la selección.#1347
Pulido de la tabla de URL de #1347: selecciona varias filas y copia exactamente la selección como TSV.
#1347 (incidencia en GitHub)AñadidoBetaControl del ritmo de rastreo en vivo: núcleo (trabajo en curso).#1360
El núcleo que permite cambiar la velocidad de rastreo mientras se ejecuta un escaneo (#1360); la conexión con Escritorio llega después.
#1360 (incidencia en GitHub)
Días anteriores (4)Show all
14 de octubre de 2026
3 cambiadoCambiadoBetaEscritorio: progreso del escaneo, límite de URL, botón de parada y motivos de#1358
finalización.
Completadas, en cola, velocidad y tiempo restante estimado, así como el límite de URL solicitado, se muestran en la lista de escaneos, en los detalles del escaneo y en la tarjeta de navegación. El control de la barra superior se llama Stop scan en lugar de mostrar un id de ejecución, se actualiza sin parpadeos y se oculta cuando la ejecución termina; las ejecuciones finalizadas indican por qué acabaron (límite de URL, de solicitudes o de tiempo, errores o disco).
#1358 (incidencia en GitHub)CambiadoBetaEscritorio: un solo sistema de botones, márgenes de página estándar y sin chips de
funciones no disponibles.
Un único sistema de botones en todas las pantallas, márgenes de página estándar, y se eliminan los chips de las funciones no disponibles.
CambiadoBetaEscritorio: el generador de redirecciones y el editor de snippets pasan a una sección de
Herramientas.
Methods contiene solo el catálogo de métodos y muestra el escaneo seleccionado al abrirse; el editor de snippets preselecciona el contexto del escaneo seleccionado.
13 de octubre de 2026
3 cambiadoCambiadoFuncionaEscritorio Crawler: pestañas de detalle de URL (enlaces entrantes, salientes, recursos,#1349
snippet, fuente guardada, cabeceras HTTP) sobre el archivo del rastreo, con filtros por pestaña y recuentos, un resumen más completo con directivas, un selector de columnas por pestaña conectado a las columnas de exportación, ordenación por encabezado, menú contextual y navegación por teclado; New scan puede guardar sus ajustes como un perfil de rastreo con nombre.
#1349 (incidencia en GitHub)CambiadoFuncionaEscritorio: superficies sin conectar: la sección Link graph lee totales de nodos, aristas#1347
y páginas huérfanas, y una página…
Escritorio: superficies sin conectar: la sección Link graph lee los totales de nodos, aristas y páginas huérfanas, y una tabla paginada de nodos desde el comando del núcleo
#1347 (incidencia en GitHub)scan-graph, en lugar de un marcador de posición. Issues enumera los grupos de comprobaciones más grandes a partir de los contadores por comprobación del núcleo, y la tabla de URL muestra y ordena la columna Inlinks (con una nota alternativa cuando un escaneo no conservó observaciones de enlaces); la columna Issue count, que nunca podía medirse, ya no se ofrece. Exportación e informes ejecutan el comando del núcleoscan-exportpara páginas o hallazgos en CSV, XLSX, JSON o XML en la carpeta elegida; se eliminan los conjuntos de datos de comparación y de tareas, la columna de marcador y el historial de exportación que el núcleo no puede respaldar. Los ajustes guardados pero aún no aplicados aparecen ahora desactivados de forma visible, con el motivo al pasar el cursor. El diálogo de configuración del rastreo enumera una sola vez, en solo lectura, los parámetros sin editor validado, en lugar de mezclarlos con la lista del editor, y el campo «Why this scan» de New scan explica por qué está vacío.CambiadoFuncionaEscritorio: superficies sin conectar: la sección Crawler ejecuta un rastreo puntual sin#1347
proyecto.
Escritorio: superficies sin conectar: la sección Crawler ejecuta ahora un rastreo puntual sin proyecto. El campo de dirección, el conmutador Site/List/Sitemap, el límite de URL, Start/Stop, las pestañas de comprobaciones, la búsqueda por dirección, los contadores de la vista general, el panel de detalles y la exportación CSV/XLSX están conectados a los comandos del núcleo
#1347 (incidencia en GitHub)crawl-site --scan-outyscan-url-query; la barra de estado muestra las cifras propias del núcleo de velocidad, rastreadas y restantes. Nada se inicia al abrir la pantalla, y el resultado temporal se elimina al pulsar Clear, en el siguiente rastreo y al cerrar la aplicación. Las entradas del menú de rastreo rápido abren la sección. Se elimina la insignia «Unavailable in this core version» de la barra superior. Compare ya no se abre en estado de error tras leer un proyecto: una comparación vacía es un aviso neutral para elegir dos escaneos, y solo un fallo real muestra el estado no disponible.
12 de octubre de 2026
8 añadido10 cambiado2 corregidoCorregidoFuncionaCorrige la compatibilidad de la configuración de escaneo nativo entre actualizaciones y#1344
reversiones. Se conservan la cabecera y la huella existentes, las nuevas opciones efectivas se guardan en un contexto versionado, y el comportamiento heredado de parámetros de seguimiento se mantiene cuando falta ese contexto. Al reanudar se valida el conjunto completo de ajustes efectivos y se rechazan los artefactos no compatibles o inconsistentes.
#1344 (incidencia en GitHub)CorregidoFuncionaCorrige la detección de RDFa conservado para que las IRI de propiedad relativas y los#1344
hosts no relacionados no establezcan marcado Schema.org. Se conservan las IRI de vocabulario absolutas y los prefijos reconocidos, y las pruebas de plazo de búsqueda siguen acotadas con patrones de datos de prueba poco costosos.
#1344 (incidencia en GitHub)CambiadoFuncionaLas pestañas compactas de ajustes del proyecto se mantienen dentro de la ventana, y los#1315
ajustes adicionales se muestran en un menú de desbordamiento. Se oculta el selector de programación redundante cuando solo está disponible el sitio principal, manteniendo la selección entre sitios vinculados en ambos tamaños de ventana. - Se muestra la vista previa de User-Agent personalizado solo cuando su valor está disponible; un nombre de preajuste no se presenta como la cabecera realmente enviada. Se conservan los límites de retardo configurados del programador. - Se reevalúa la creación de tareas de propietario tras actualizar el proyecto, y las ejecuciones de competidores compatibles validadas por el núcleo se conservan entre revisiones de checklist no relacionadas. La confirmación y las comprobaciones de la revisión actual siguen siendo obligatorias para las escrituras. - La verificación de bots se desactiva hasta que haya registros de proyecto conservados, se admiten las llamadas habituales de Qt a modelos de tabla, y los totales guardados de incidencias se muestran por separado de las muestras acotadas de URL y de las comprobaciones no medidas. - Las fuentes incluidas se registran una vez por aplicación, en lugar de duplicarse en cada cambio de tema.
#1315 (incidencia en GitHub)AñadidoFuncionaAñade gestión de credenciales de proveedor solo de escritura por el canal stdin de la CLI#1343
local, con consentimiento OAuth de GSC explícito…
Añade gestión de credenciales de proveedor solo de escritura a través del canal stdin de la CLI local, ciclo de vida explícito del consentimiento OAuth de GSC y descubrimiento de recursos de cuenta solo en vista previa; la selección de proveedor y las escrituras de credenciales MCP quedan sujetas a decisiones explícitas del propietario. - Añade hallazgos acotados de URL Inspection a la salida de SF vinculada a un proyecto, tras la opción explícita
#1343 (incidencia en GitHub)--gsc-inspect, con contabilidad local de cuota por propiedad y un historial de inspecciones conservado y con lista de permitidos. SF también une el historial medido de URL de GSC, GA4, Metrika y Cloudflare sin llamadas implícitas a proveedores; los hallazgos por URL registrados entran en el flujo ordinario de incidencias de la auditoría, mientras que la cobertura ausente o parcial se indica de forma explícita. - Añade instantáneas diarias agregadas por URL de Cloudflare, importación explícita de Enterprise Logpull, importación de NDJSON de Logpush aportado por el usuario a través del almacén local de logs, y lecturas de solo lectura y opcionales de los ajustes de IA, de los conjuntos de reglas de redirección/WAF y de los trabajos de Logpush. Una captura de Instant Logs, confirmada por separado y sujeta al plan, usa una sesión WebSocket breve y acotada y conserva solo un prefijo local limitado; la ruta no toca las sesiones existentes e informa del vencimiento por inactividad documentado por Cloudflare, porque la API Edge no ofrece endpoint de parada. Los flujos de destino de Logpush siguen siendo propiedad del cliente y no se ingieren. - Añade una operación explícita de backlinks JSON-RPC actual de Moz, manteniendo las métricas de URL heredadas como opción predeterminada, y deja los recibos de gasto inciertos como null en los informes de registro. - Añade un lector acotado de resumen de artefactos de PageSpeed que valida la propiedad y devuelve solo campos de Lighthouse incluidos en la lista de permitidos.CambiadoFuncionaLos perfiles de rastreo con nombre se pueden inspeccionar como JSON validado, seleccionar#1299
con
seo_crawl_site…Los perfiles de rastreo con nombre se pueden inspeccionar como JSON validado, seleccionar mediante
#1299 (incidencia en GitHub)seo_crawl_sitey asignar como predeterminados del proyecto, con las anulaciones de rastreo del proyecto superpuestas encima. - El progreso del rastreo estima el tiempo para la frontera conocida actual y lo indica por separado de la duración total del rastreo; los destinos de rastreo normalizan por defecto los parámetrosutm_*yfbclid. - Los escaneos nativos activos de proyecto aceptan solicitudes puntuales de pausa y detención por id de ejecución y checkpoint, a través de la ruta de recuperación SQLite existente. - La autenticación HTTP Basic/Digest vinculada a un host y la negociación opcional de respuestas zstd usan referencias a variables de entorno, confirmación explícita, autenticación solo por HTTPS y presupuestos de solicitudes. Los resultados del rastreo incluyen estimaciones acotadas de carga y conservan como null el tamaño de disco desconocido.AñadidoFuncionaAñade un resumen operativo del estado del proyecto: progreso de los colectores activos,#1291
integridad del último escaneo…
Añade un resumen operativo del estado del proyecto con el progreso de los colectores activos, la integridad del último escaneo completado, el estado de las carpetas, las tareas abiertas del proyecto principal, la última actividad registrada de agentes y el tamaño persistido del directorio de escaneos; el estado de conexión sigue como desconocido sin un heartbeat en vivo.
#1291 (incidencia en GitHub)AñadidoFuncionaAñade un contrato de información del núcleo legible por máquina, con revisión y hora de#979
compilación verificadas, herramientas CLI y MCP compatibles y compatibilidad exacta por revisión con Escritorio; añade un comando
#979 (incidencia en GitHub)doctorgeneral de solo lectura y una herramienta MCP para comprobar los requisitos previos locales.seohead --versionmuestra la versión del paquete. - Añade lecturas condicionales opacas y sensibles a la revisión paraproject-observeyproject-activity; añade comprobaciones de versiones que requieren consentimiento y descargas de wheel/fuente con verificación de checksum, con progreso, cancelación y sin instalación automática.AñadidoFuncionaAñade estimaciones de comprobación previa de las fases de pago e historial de estado por#1298
fase a los proyectos de semantic-core. - Admite vistas previas de importación CSV/XLSX con mapeo, exportaciones acotadas por alcance, lecturas paginadas de clústeres, selecciones de landing page auditadas y perspectivas locales basadas en evidencias.
#1298 (incidencia en GitHub)AñadidoFuncionaAcciones de página y preajustes acotados, activables por proyecto, en los rastreos#1302
renderizados; diferencias de versión sin procesar frente a renderizada conservadas…
Se añadieron acciones de página y preajustes acotados, activables por proyecto, a los rastreos renderizados; se conservan las diferencias entre elementos sin procesar y renderizados y los fallos de red del navegador. Se exponen hallazgos de desbordamiento móvil, tamaño de texto y tamaño de objetivo a partir de los diseños renderizados capturados. Se añadió captura de la primera pantalla y metadatos explícitos de representación del DOM.
#1302 (incidencia en GitHub)AñadidoFuncionaSe añadieron los estados exactos
checks_run,checks_skipped,checks_disabledy los#1296totales del registro a las evidencias de escaneos guardados…
Se añadieron los estados exactos
#1296 (incidencia en GitHub)checks_run,checks_skipped,checks_disabledy los totales del registro a las evidencias de escaneos de proyecto guardados. Los recuentos evaluados y omitidos siguen siendo disjuntos, y la cobertura de auditoría ausente se informa como no disponible. - Los escaneos guardados exponen ventanas acotadas de HTML estático y renderizado con identidad de escaneo y de documento, hashes del cuerpo sin procesar y del texto decodificado, y páginas de hallazgos por URL exacta a través de los manejadores compartidos de CLI y MCP. El detalle de URL incluye una ventana acotada del HTML fuente; la evidencia no disponible o ambigua se mantiene explícita. La comparación de cuerpos admite pares estático/renderizado además de pares entre escaneos. - El estado del escaneo informa de la integridad, del escaneo afectado, de la disponibilidad de checkpoints y de recuentos de daños anulables. Los archivos portables de proyecto pueden omitir todos los cuerpos HTML, omitir los cuerpos de más de 30 o 90 días, o conservar solo los N escaneos reconocidos más recientes, manteniendo las tablas de evidencias.CambiadoFuncionaConsultas de URL de escaneos guardados ampliadas con recuentos de enlaces conservados,#1295
filtros de título, canonical, hreflang y sitemap, y facetas según la fuente. Las mediciones ausentes de enlaces, sitemap, hreflang o auditoría siguen como no disponibles en lugar de aparecer como cero. - Se añadieron contadores de severidad por escaneo completo y por comprobación a partir del resumen de auditoría guardado, incluidos los estados explícitos de comprobación disparada, silenciosa, omitida, desactivada y no disponible. - Se persiste un índice de profundidad de clic mínima reconstruible al terminar una captura scan.v2 o un reanálisis sin conexión; los archivos de escaneo anteriores siguen derivando la profundidad de su grafo de enlaces conservado dentro del presupuesto de consulta. - Se añadieron filtros de recursos por tipo y URL vinculados al documento de origen, recuentos por aparición y por tipo, estados de bytes conservados y agregados de bloques y pesos en la evidencia de recursos guardada; las declaraciones no disponibles y los pesos de descarga parciales siguen explícitos. - Se capturan en scan.v2 los tiempos de TCP/conexión, TLS, espera de cabeceras de respuesta y descarga del cuerpo de HTTPX cuando el transporte emite eventos de traza. DNS sigue no disponible porque HTTPX no expone un evento de resolución separado; su tiempo puede estar incluido en la conexión. Se añadió
#1295 (incidencia en GitHub)headers-analyzesin conexión para las cabeceras y la evidencia de fases redactadas guardadas. - Se añadió una lectura de árbol de directorios por CLI/MCP con agregación SQLite temporal, con profundidad, número de hijos, número de nodos y bytes de salida acotados. Las lecturas de ruta más corta existentes siguen disponibles mediantescan-link-inspect --view path. - Se añadióscan-link-inspect --view links --preset inlinks|broken_linkspara vistas con nombre de enlaces internos entrantes y de destinos salientes rotos. - La finalización nativa de scan.v2 y el reanálisis sin conexión intentan ahora una proyección indexada opcional de consulta de URL vinculada a la fuente, para recuentos y tipos de recursos por página, marcas de título duplicado, cobertura y facetas sin filtrar. Las lecturas solo la aceptan para un escaneo terminado con UUID de escaneo, revisión de evidencia, capacidades y URL de inicio coincidentes; reencolar invalida su publicación. Los escaneos anteriores mantienen la lectura alternativa acotada y de solo lectura, sin migración de scan.v1. En el accesorio sintético de un escaneo terminado de 1M de páginas con HTML e imágenes compartidas, el productor real de la proyección terminó en 6,36 s con un pico de 400,7 MB de RSS. Las medianas de cinco ejecuciones fueron de 5,23–43,38 ms para páginas con columnas de recursos, 60,81 ms para el filtro de imágenes y 5,38 ms para todas las facetas, dentro de los presupuestos de 200/300 ms; 100 filas de imágenes fueron exactas. Esto valida el rendimiento de consultas guardadas sintéticas, no un rastreo real de 1M de URL. Los enlaces entrantes y las facetas de sitemap siguieron explícitamente no disponibles, así que la respuesta de facetas fue parcial.CambiadoFuncionaEl checklist de proyecto v4 incluye responsables, criterios de aceptación, enlaces a#1294
incidencias y métodos, límites de URL de competidores…
El checklist de proyecto v4 incluye responsables, criterios de aceptación, enlaces a incidencias y métodos, límites acotados de URL de competidores y comentarios de tareas atribuidos y de solo adición, manteniendo la lectura de formatos de cobertura anteriores. - Al aceptar un objetivo del buzón se crea su tarea personalizada estable del checklist, con el objetivo original como descripción; la aceptación sigue sin ejecutar ni completar la tarea. - Las vistas de tareas e informes muestran estados de medición honestos por tarea para las URL afectadas, así como KPIs de tareas personalizadas; los recuentos siguen no disponibles cuando la evidencia conservada no enumera las URL afectadas.
#1294 (incidencia en GitHub)CambiadoFuncionaLos informes Markdown, DOCX y XLSX vinculados a un proyecto incluyen recuentos de tareas#1297
personalizadas, asignación y criterios de aceptación…
Los informes Markdown, DOCX y XLSX vinculados a un proyecto incluyen recuentos de tareas personalizadas, campos de asignación y de criterios de aceptación, y la evidencia anulable de URL afectadas con su estado de medición.
#1297 (incidencia en GitHub)AñadidoFuncionaAñade metadatos de categoría y de reconocimiento de proyecto con paginación por#1312
desplazamiento al catálogo de herramientas MCP, y un lote acotado de comprobación de URL para listas explícitas o páginas de escaneos conservados. - Añade optimización automática de calidad de imagen guiada por SSIM, eliminación explícita de EXIF e informes de optimización de imágenes de escaneos conservados; añade salida CSV de WordPress Redirection con análisis local de cadenas y bucles. - Muestra las banderas heredadas de profundidad y retardo de rastreo en la ayuda y mantiene su comportamiento de compatibilidad.
#1312 (incidencia en GitHub)AñadidoFuncionaLecturas de flujo compare.v2 acotadas con comprobaciones de integridad, ordenación y#1300
filtrado por URL; genera un resumen Markdown acotado…
Añade lecturas de flujo compare.v2 acotadas con comprobaciones de integridad, ordenación y filtrado por URL, y genera un resumen Markdown acotado y tarjetas antes/después por URL exacta que conservan las observaciones ausentes como no recomprobadas. - Amplía el historial guardado de URL con datos de página y deltas entre escaneos adyacentes; las observaciones no disponibles o ausentes siguen sin ser comparables. - Persiste checkpoints de comparación e instantáneas de progreso para reanudar con una entrada exacta, reutiliza los paquetes completados y verificados como aciertos de caché, y añade cortes por segmento principal en cada cambio y evidencia de códigos de respuesta de enlaces externos conservada.
#1300 (incidencia en GitHub)CambiadoFuncionaAmplía el lector de datos estructurados conservados por URL exacta con JSON-LD,#1304
Microdata, RDFa…
Amplía el lector de datos estructurados conservados por URL exacta con JSON-LD, Microdata y RDFa acotados, evidencia de idioma, linaje de fuentes y validación local sin conexión de Schema.org.
#1304 (incidencia en GitHub)CambiadoFuncionaLa búsqueda de contenido conservada informa de ocurrencias acotadas con desplazamientos#1301
de caracteres en el texto fuente, líneas numeradas desde uno, navegación de coincidencias por documento y ventanas opcionales redactadas de seis líneas. El filtrado por URL exacta se ejecuta antes de que SQLite ordene los documentos conservados. Los recuentos completos de coincidencias siguen visibles cuando el límite de 10 000 desplazamientos o de 64 KiB trunca las ocurrencias devueltas, y la cobertura es parcial. Las búsquedas con expresiones regulares no están disponibles cuando no se puede imponer un plazo de reloj de pared; los cuerpos no disponibles siguen siendo desconocidos, nunca ausentes. - Los paquetes de búsqueda indexados están limitados a 512 MiB; al alcanzar el límite se publica un paquete explícitamente incompleto, con su cobertura medida y su límite de bytes. - Se añadió una ruta sin conexión de muestra de extracción personalizada para HTML aportado por el usuario. Su URL opcional es solo una etiqueta y no provoca ninguna descarga; la obtención de URL en vivo sigue siendo una decisión del propietario.
#1301 (incidencia en GitHub)CambiadoFuncionaImporta filas CSV de edición de snippets en tareas de revisión sin aplicar, mide la#1010
tipografía local según el perfil definido por el llamante y añade extractos de consulta de escaneos guardados seleccionados explícitamente, con linaje de documento; no se infiere ningún umbral de motor de búsqueda ni afirmación de renderizado.
#1010 (incidencia en GitHub)CambiadoFuncionaLos rastreos nativos almacenados comparan cuerpos de respuesta conservados con un#1013
conjunto acotado de familias reconocibles de Content-Type…
Los rastreos nativos almacenados comparan los cuerpos de respuesta conservados con un conjunto acotado de familias reconocibles de Content-Type; los cuerpos no disponibles, sobredimensionados o ambiguos siguen sin medirse de forma explícita.
#1013 (incidencia en GitHub)CambiadoFuncionaEl análisis nativo de imágenes conservadas informa de declaraciones de tamaño ausentes o#1303
no válidas y de texto alternativo vacío informativo o malformado, y mantiene el
#1303 (incidencia en GitHub)alt=""decorativo válido. Los atributos alt ausentes literales siguen siendo hallazgos con un nombre ARIA; las imágenes decorativas visibles todavía necesitan tamaños. - Los hallazgos de imagen conservan el alcance de origen, destino y estado, el motivo, el documento y las ubicaciones ordinales acotadas. Los cuerpos ausentes conservan los hechos positivos conocidos de recuento de páginas, sin inventar una URL de imagen ni una respuesta de recurso. Los errores de respuesta de imagen y los umbrales de bytes conservan estado y motivo. - La selección de imágenes resuelve las páginas de origen tras reabrir. La evidencia de recursos nombra junto a los documentos de origen las filas conservadas de obtención y declaración. La identidad de imagen nativa incluye la página de origen y el alcance, evitando deliberadamente colapsar entre páginas, y migrando las huellas nativas de imagen anteriores. Los hallazgos heredados sin página de origen mantienen su identidad anterior; los elementos repetidos conservan recuentos exactos y muestras acotadas de ubicación. - La tienda sintética conserva los defectos originales y 15 controles, y añade casos de alt vacío informativo y de tamaño ausente en productos existentes sin cambiar los recuentos del rastreo.
11 de octubre de 2026
16 cambiadoCambiadoFuncionaEjecuta la suite completa del toolkit una sola vez en Python 3.15 en lugar de una matriz
de versiones anteriores, conservando…
Ejecuta la suite completa del toolkit una sola vez en Python 3.15, en lugar de una matriz de versiones anteriores, conservando cuatro grupos de pruebas verificados y la cobertura combinada. Usa la misma versión estable de Python para los arranques de CI y de compilación de releases.
CambiadoFuncionaConsolida las comprobaciones de auditoría conservadas y las mejoras de escritorio nativo.
Preserva los ajustes de presupuesto de recursos sin cambiar la cabecera de escaneo congelada, conserva el reanálisis y la reanudación seguros sin conexión, y comparte los componentes nativos de ajustes del proyecto, los tokens de tema y las fuentes incluidas. Elimina los insumos de diseño privados del árbol distribuido. - Vincula las comprobaciones de remediación a la política de activos efectiva validada, conservando la cabecera de escaneo original y los bytes de origen.
CambiadoFuncionaRehace Project settings (Schedule y Crawl) con componentes nativos de lienzo compartidos,#1323
fuentes Roboto sin conexión…
Rehace Project settings (Schedule y Crawl) con componentes nativos de lienzo compartidos, fuentes Roboto y Material Symbols sin conexión y un diseño de una sola columna a 800 px. - Usa inglés en toda la interfaz de la aplicación, conserva el comando de programación existente y los contratos de documentos, y muestra solo datos de programación respaldados por el núcleo. - Conserva las identidades y alias de los espacios de trabajo mientras Project settings está abierto, e impide guardar varias veces mientras el núcleo está respondiendo.
#1323 (incidencia en GitHub)CambiadoFuncionaEscritorio: los ajustes del proyecto ganan una pestaña Schedule (días laborables, días#1322
del mes, ventana de ejecución, zona horaria…
Los ajustes del proyecto de escritorio ganan una pestaña Schedule (días laborables, días del mes, ventana de ejecución, zona horaria, competidores) y una pestaña Crawl (modo de rastreo, preajuste o cadena personalizada de User-Agent, pausa entre solicitudes, presupuesto de URL, SpiderHeadBot o un user agent personalizado); ambas leen y escriben el proyecto a través del núcleo, y la vista general del proyecto muestra la próxima y la última ejecución programada. Un modo --tray ejecuta los escaneos vencidos del núcleo y mantiene el Mac despierto solo mientras se ejecuta un escaneo.
#1322 (incidencia en GitHub)CambiadoFuncionaLas auditorías nativas exponen el marcado del head que bloquea el renderizado a partir#1303
del HTML conservado completo, sin cambiar…
Las auditorías nativas exponen ahora el marcado del head que bloquea el renderizado a partir del HTML conservado completo, sin cambiar el esquema congelado scan.v1. Los cuerpos incompletos, ausentes o limitados por presupuesto siguen no disponibles. Se reutilizan la detección existente de recursos del head y la entrada de extracción personalizada de SF. - Añade presupuestos nativos configurables de navegación observada y de bytes por recurso individual, señales de caché y entrega de fuentes, heurísticas de minificación y de scripts heredados, y duplicados exactos de scripts en la misma página a partir de la evidencia scan.v2 conservada. Los datos no descargados y las cargas de tiempo de ejecución incompletas siguen siendo explícitos; las declaraciones responsivas no se suman como peso de ejecución. Los límites inferiores solo de HTML, los recuentos escalares de cobertura, las muestras de fuentes y los resúmenes de origen siguen explícitos y acotados. - Recoge la cobertura precisa acotada de JS/CSS de Chromium en renders solicitados, conserva resúmenes de uso UTF-16 y hallazgos renderizados de dimensionado de imágenes, y los lee tras reabrir o en reanálisis sin conexión. Los motores no compatibles y las mediciones ausentes no se convierten en resultados limpios. - Acepta JSON de Lighthouse acotado y coincidente por URL para el descubrimiento de LCP, árboles de dependencias, responsables de cambios de diseño, entrega de imágenes, reflujo forzado y hallazgos de ejecución de scripts, con procedencia de la captura y hashes de entrada. No se añade ningún proceso de Lighthouse, proveedor de pago ni inferencia de Core Web Vitals de campo. Actualiza el registro, la cobertura de SF y la documentación de referencia generada. - Mantiene los valores exactos de los umbrales de activos adicionales fuera de la cabecera de escaneo nativa congelada y los guarda en un contexto de ejecución validado y versionado. La reanudación compara estos valores por separado, y el reanálisis sin conexión los restaura desde la evidencia conservada; los lectores ligeros anteriores pueden seguir inspeccionando la forma sin cambios de la configuración de la cabecera.
#1303 (incidencia en GitHub)CambiadoFuncionaConserva la evidencia AMP estática y de accesibilidad vinculada al documento en las filas#1304
de contexto de escaneo existentes, preservando el esquema SQL congelado
#1304 (incidencia en GitHub)scan.v1. Los hallazgos AMP estructurales inspeccionan el doctype original, head/body, el charset UTF-8, el viewport, el script de ejecución y las declaraciones de boilerplate; los destinos AMP emparejados sin marcador de raíz AMP se identifican por separado. Las reglas completas del validador AMP siguen no disponibles a la espera de una decisión de licencia. - Inicia hallazgos de accesibilidad para el idioma del documento, las etiquetas de formularios, las alternativas de imagen, los saltos de encabezado y el landmark principal. Los hallazgos conservan ejemplos acotados y recuentos completos de ocurrencias. El contraste calculado y las reglas renderizadas de axe-core siguen sin medirse. - Valida los sujetos y propiedades de Schema.org Microdata y RDFa comunes con el vocabulario incluido y las reglas existentes de resultados enriquecidos. Los errores, advertencias y propiedades obligatorias ausentes conservados por URL se convierten en hallazgos nativos. Las construcciones RDFa no compatibles son evidencia parcial explícita, no un resultado de validación limpio. - Sirve los árboles JSON-LD parseados junto con el origen de cada bloque, su posición y los errores de sintaxis enscan-structured-blocks; limita los árboles de propiedades anchos y expone ese límite. Lee el último documento de una URL solicitada y de una representación sin cambiar su escaneo. - Conserva la evidencia estructurada parcial o no disponible sin ocultar los errores hermanos confirmados. Resuelve las identidades JSON-LD compatibles frente a la misma base de documento que el marcado HTML, preservando el JSON fuente; rechaza los bloques JSON escalares o vacíos como grafos válidos y comparte la selección normalizada de etiquetas JSON-LD vivas entre el parser y las proyecciones servidas.CambiadoFuncionaConserva los atributos canonical y de paginación sin procesar como contexto de documento#1305
versionado, sin cambiar el SQL congelado del escaneo. Los enlaces canonical con atributos hreflang/lang/media/type no compatibles, las anotaciones mal formadas y las declaraciones entre hosts o protocolos distintos generan ahora hallazgos vinculados a la evidencia; las palabras clave de relación bien formadas pero desconocidas siguen sin clasificar. - Amplía las sondas acotadas de destino del mismo host a la paginación y conserva observaciones medidas de noindex/canonical. Las cadenas canonical nativas y los hallazgos de noindex en canonical/hreflang pueden usar sondas; las sondas heredadas solo de estado siguen siendo legibles y sin medir para las directivas HTML. - Juzga las cadenas de paginación nativas opacas en busca de contradicciones recíprocas explícitas de next/prev, conservando las reglas numeradas y de paso y los estados sin juzgar con nombre. Selecciona las URL de hallazgos guardados, incluidos los miembros de grupos, mediante scan-url-query con tablas SQLite temporales y evidencia audit.v2 en streaming. - Mantiene los tokens de relación Unicode y con signos de puntuación sin clasificar, normaliza las autoridades canonical IDN y de puerto por defecto equivalentes, y preserva las rutas exactas de destino de paginación nativa. Los tokens de página mixtos ilegibles siguen sin juzgar; el defecto de paginación de la tienda se recupera aunque la página uno no tenga número en su URL. - Renderiza las anotaciones next/prev declaradas de la tienda de prueba para que su verdad de referencia de paginación D41 se sirva y pueda validarse mediante captura nativa.
#1305 (incidencia en GitHub)CambiadoFuncionaLos logs de servidor conservan ahora totales exactos de IP de bots respaldados en disco#1311
en lugar de una muestra limitada, con límites…
Los logs de servidor conservan ahora totales exactos de IP de bots respaldados en disco en lugar de una muestra limitada, con registros acotados por IP, visitas, última visita y filtros por subred. La verificación DNS explícita comprueba cada IP seleccionada por separado, registra evidencia PTR y de resolución directa, admite IPv6 y conserva los resultados no disponibles o con tiempo agotado como no comprobados. Las cachés locales caducan tras una hora; las lecturas nunca lanzan consultas DNS. - Se añadieron la importación local de logs del proyecto, el resumen paginado, la evidencia de bots y los comandos de unión con escaneos nativos, a través de los manejadores compartidos de CLI/MCP. Los artefactos de logs separados conservan particiones por fecha y la cobertura y procedencia de las fuentes sin cambiar los esquemas congelados de escaneo. Las evidencias incompletas o ausentes retienen las conclusiones de ausencia. Las pantallas de logs de Escritorio siguen siendo un seguimiento de presentación aparte.
#1311 (incidencia en GitHub)CambiadoFuncionaLas auditorías nativas conservadas agrupan ahora los enlaces internos rotos por destino#1306
observado, con evidencia de origen y texto ancla, registran cadenas y bucles de redirección con estados por salto, distinguen las búsquedas internas basadas en ruta y los anclajes vacíos, y exponen los resultados capturados de enlaces externos sin respuesta. Las comprobaciones de coherencia de sitemap y robots.txt usan la pertenencia conservada y la evidencia de respuesta sin nuevas descargas en vivo; la evidencia ausente o parcial sigue explícita. - Se añadió un grafo de enlaces acotado de escaneos guardados, con filtros por posición, sección y vecindario local, agregación por sección y cambios de aristas entre escaneos. El reanálisis sin conexión rellena las posiciones con lotes derivados reanudables y notifica la evidencia no clasificada en la inspección de enlaces y en el estado del escaneo, preservando el esquema congelado scan.v1. - Se añadió generación local de sitemap XML a partir de páginas 200 canonical e indexables conservadas, con lastmod observado, exclusiones, división por protocolo, índice de sitemap y sitemap de imágenes opcional. CLI y MCP comparten las mismas implementaciones; la publicación de la salida exige un directorio local nuevo y nunca despliega archivos. - Conserva los destinos de descubrimiento ausentes registrados en el momento de la captura cuando un sitemap o un procesamiento posterior de semillas añade la URL al catálogo conservado. La evidencia explicada de no resuelto o excluido permanece inmutable, mientras que los destinos conocidos declarados y las discrepancias de identidad no nulas siguen siendo inválidos. - El sitemap de imágenes excluye las respuestas de recurso no-200 conocidas aunque el recurso no se haya guardado como página rastreada, y marca las respuestas de imagen no medidas como cobertura parcial.
#1306 (incidencia en GitHub)CambiadoFuncionaProtege las llamadas de producción de Google DataForSEO antes de construir el cliente,#1310
expone cotizaciones sin conexión a partir de precios de proveedor proporcionados, tiene en cuenta la profundidad de SERP y los cargos por operadores de búsqueda, y aplica techos conocidos en USD por llamada antes del transporte. Amplía las operaciones acotadas del índice de backlinks y registra los costes ausentes o las formas de respuesta mal formadas como recibos inciertos. Los límites de moneda por proyecto y por mes siguen pendientes de decisión del propietario. - Fusiona la evidencia explícita de origen e importación de backlinks en instantáneas privadas de historial local, con todas las observaciones de tokens rel, anclas, dominios de referencia, filtros y señales transparentes de revisión de spam. Añade rutas CLI/MCP de perfil y de exportación de disavow revisada, sin envíos automáticos. - Añade avisos de revisión de tokens rel mixtos y de divulgación patrocinada de enlaces salientes a partir de la evidencia nativa conservada, conservando el contexto no disponible, recuentos nulos para poblaciones de HTML enteramente no analizadas, y las clases sponsored/ugc/nofollow en informes y en las comprobaciones de donantes, sin cambiar el esquema congelado de escaneos conservados.
#1310 (incidencia en GitHub)CambiadoFuncionaLas comprobaciones nativas de DOM y de duplicados leen ahora el documento conservado#1307
seleccionado de cada página por URL exacta, con linaje verificado de respuesta y cuerpo. La retención deshabilitada, los cuerpos ausentes, no válidos o que superan el presupuesto siguen como omisiones explícitas; los hallazgos parciales llevan cobertura. Los hashes exactos del área de contenido y los hallazgos SimHash/LSH acotados se persisten en la auditoría nativa sin requerir un directorio HTML de SF. Las bandas LSH adaptativas al umbral preservan la sensibilidad de los pares que cumplen el criterio, reduciendo los cubos de candidatos amplios; el agotamiento del presupuesto de análisis aproximado no descarta los hallazgos de hash exacto. - Las auditorías de SF ejecutan opcionalmente la similitud semántica y la revisión de título/H1 frente al cuerpo conservado, mediante un adaptador local aportado explícitamente o incrustaciones declaradas. No se selecciona automáticamente ningún modelo ni proveedor. La identidad del adaptador, los hashes de origen, las puntuaciones, los límites y las omisiones acompañan a los candidatos de revisión; la similitud semántica no afirma contenido duplicado, relevancia de consulta ni canibalización. Las dos filas semánticas de cobertura de SF siguen como huecos hasta que se seleccione y valide un adaptador real. La autorización de proveedores externos requiere el booleano literal
#1307 (incidencia en GitHub)true; las cadenas o enteros truthy nunca autorizan una llamada de incrustación.CambiadoFuncionaLas referencias del buzón aceptan ids de objetivo (
inbox:<uuid>), para que una nota#1314pueda citar el objetivo al que se refiere. - Los elementos del checklist que nunca se intentaron y son manuales muestran el estado
#1314 (incidencia en GitHub)not_runen lugar dereview; solo un intento pendiente de decisión permanece enreview. - El modelo de lectura de Issues (evidencia de hallazgos deobserve) informa de recuentos por comprobación (by_check) y de unnext_offsettras los primeros 20 hallazgos;findings_pagepagina el resto.CambiadoFuncionaEscaneos de proyecto programados (#1322, núcleo):
schedule.jsonen cada directorio de#1322proyecto guarda la programación independiente de ese sitio (días laborables y/o días del mes, una ventana horaria en la zona horaria del sitio, activar o desactivar, modo de rastreo
#1322 (incidencia en GitHub)spider/sitemap/list, presupuestos de URL y de solicitudes por ejecución, retardo de cortesía, user agent y estado de reanudación por segmento relativo al proyecto). El proyecto propietario puede incluir competidores vinculados, cada uno con su propia cadencia y política de escaneo. Los ajustes se editan conschedule-set/seo_schedule_setyexpected_revision;schedule-showinforma del estado de vencimiento y de la próxima ejecución del principal y de los competidores vinculados.schedule-run-duees un punto de entrada sin interfaz que ejecuta solo los escaneos que vencen de forma independiente, mantiene bloqueos con alcance de proceso hasta que termina cada ejecución, registra el estado de cancelación antes de relanzarla, y anota en cada proyecto afectado los resultados o el solapamiento de competidores.schedule-installyschedule-uninstallescriben o eliminan un plist de launchd, una línea de cron o un comando de Task Scheduler solo cuando se invocan explícitamente. - Agentes de usuario de rastreo: preajustes (spiderhead,googlebot,googlebot-desktop,googlebot-smartphone,bingbot,yandexbot,yandexmobilebot,baiduspider,duckduckbot,applebot,gptbot,claudebot,perplexitybot, y navegadores de escritorio y móviles) o una cadena personalizada. El valor predeterminado es ahoraSpiderHeadBot/<version> (+https://github.com/PavloSEO/spiderhead), y la coincidencia del grupo de robots.txt usa la misma identidad. Los sitios que coincidían con el antiguo grupo de robots deSEOHEAD-Toolsdeben nombrarSpiderHeadBoten sus reglas.CambiadoFunciona
workflow-startsolo necesita un objetivo de propietario aceptado: basta con--goal-id#1314(o
#1314 (incidencia en GitHub)context.goal_id). El prompt registrado usa por defectoskill:workflow/full-audit-v1y la tarea del checklist usa por defecto la que crea el objetivo aceptado (custom:goal-<entry>). Los rechazos nombran el comando del propietario que corrige el vínculo que falta. Las opciones se documentan enseohead workflow-start --help. - Las poblaciones del checklist aceptan objetos parciales: solokindysourceson obligatorios, y las demás claves toman el valor no definido por defecto. Una población rechazada indica sus claves faltantes o desconocidas. - Los rastreos de proyecto nativos recurren al/sitemap.xmldel origen cuando robots.txt no declara ningún sitemap. Una alternativa ausente se registra como incompleta, pero no interrumpe el rastreo.CambiadoFuncionaLos espacios de trabajo de competidores conservan la URL tal como se introdujo: el#1314
rastreo de un competidor parte de su URL
#1314 (incidencia en GitHub)wwwen lugar del host desnudo, y un rastreo de una URL de competidor ya no marca los elementos del checklist del propietario; el resultado se registra solo en el espacio de trabajo del propio competidor. Al abrir un proyecto con un espacio de trabajo de competidor dañado se informa de que ese competidor no está disponible, en lugar de fallar.CambiadoFuncionaLa cobertura del checklist de proyecto vincula ahora los informes audit.v2 en streaming:
report-build --projectyaudit-workflow --action reportadjuntan la instantánea del checklist a la salida de resumen en xlsx, docx, csv, md y PDF, en lugar de construir un informe sin vincular. Un escaneo detenido por su presupuesto de URL (stopped_by_budget) se acepta como último escaneo auditado del proyecto, y su informe indica el alcance limitado.report-build --inputacepta la claveformat.report-build --project --format jsonsobre una auditoría en streaming se rechaza con una explicación, porque el JSON se escribe literalmente y no puede incluir la instantánea del checklist.
Hoja de ruta
108 abiertasHitos abiertos en GitHub. Cada línea es una incidencia abierta: trabajo planificado, aún no publicado.
Lo básico del escritorio
Primero que la app de escritorio funcione: bloqueos, tamaño 800×600, pestañas muertas, estados honestos (ola 1 del plan)
AñadidoPlanificadoDesktop: recorrido del propietario en un proyecto real (visual, escaneos, incidencias,#1358
exportaciones, herramientas)
#1358 (incidencia en GitHub)- CorregidoPlanificadoDesktop: pestañas inactivas, acciones deshabilitadas y pantallas provisionales#1347 (incidencia en GitHub)
AñadidoPlanificadoWindows: fallan el rastreo nativo, el diario del proyecto y la compilación de Desktop;#1345
Desktop abre ventanas en blanco en masa y es inutilizable en 4K
#1345 (incidencia en GitHub)
Paridad del escritorio
Patrones de UX a la par: pestañas, columnas por filtro, detalle desde el resumen, diseño persistente (épica #1522)
- AñadidoPlanificadoLas pestañas de detalle admiten selecciones de varias filas#1498 (incidencia en GitHub)
- AñadidoPlanificadoUn único estado de actividad compartido para todas las ventanas y controles#1496 (incidencia en GitHub)
- AñadidoPlanificadoConjuntos de pestañas personalizables con persistencia por modo#1488 (incidencia en GitHub)
- AñadidoPlanificadoAsistente de extracción visual con sugerencias de selectores#1461 (incidencia en GitHub)
- AñadidoPlanificadoDiagrama de clústeres de contenido a partir de grupos de similitud#1460 (incidencia en GitHub)
- AñadidoPlanificadoNubes de palabras para el texto ancla y el texto del cuerpo#1459 (incidencia en GitHub)
Motor de rastreo
Cortesía y políticas de robots, reintentos, presupuestos, descubrimiento, escala de almacenamiento, ciclo del escaneo (épica #1520)
AñadidoPlanificadoRecopilar las anotaciones de canonical y paginación enviadas en la cabecera de respuesta#1517
HTTP Link, con su origen de declaración
#1517 (incidencia en GitHub)- AñadidoPlanificadoDirigir un rastreo en curso: reducción del alcance en vivo e inyección de URL#1485 (incidencia en GitHub)
- AñadidoPlanificadoRastreo opcional de rutas con identificador de fragmento#1482 (incidencia en GitHub)
- AñadidoPlanificadoLímite automático de páginas renderizadas en paralelo según la memoria disponible#1480 (incidencia en GitHub)
- AñadidoPlanificadoFallo de renderizado como resultado de URL independiente#1479 (incidencia en GitHub)
- AñadidoPlanificadoIncluir contenido de shadow DOM e iframes en la captura renderizada#1477 (incidencia en GitHub)
- AñadidoPlanificadoCapturar los mensajes de la consola del navegador por cada URL renderizada#1475 (incidencia en GitHub)
- AñadidoPlanificadoProtección de espacio libre en disco para el almacenamiento de escaneos#1474 (incidencia en GitHub)
- AñadidoPlanificadoAlternativa de compatibilidad para servidores TLS antiguos#1473 (incidencia en GitHub)
- AñadidoPlanificadoRegistrar la fuente de descubrimiento de cada URL rastreada#1471 (incidencia en GitHub)
- AñadidoPlanificadoResolver los enlaces relativos respecto a la URL base del documento#1470 (incidencia en GitHub)
- AñadidoPlanificadoGastar el presupuesto de rastreo empezando por los niveles más superficiales#1468 (incidencia en GitHub)
- AñadidoPlanificadoLa profundidad de clics refleja la ruta de descubrimiento más corta#1467 (incidencia en GitHub)
- AñadidoPlanificadoNormalización estructural de URL antes de deduplicar el rastreo#1466 (incidencia en GitHub)
- AñadidoPlanificadoDescargar robots.txt como máximo una vez por origen en concurrencia#1465 (incidencia en GitHub)
- AñadidoPlanificadoRespetar Retry-After y reducir el ritmo ante respuestas de limitación#1463 (incidencia en GitHub)
- AñadidoPlanificadoAutenticación por formulario web para rastreos renderizados#1447 (incidencia en GitHub)
AñadidoPlanificadoPresupuestos de rastreo ampliados: profundidad de carpetas, por subdominio, por nivel de#1445
profundidad, por patrón de ruta, máximo de enlaces por página
#1445 (incidencia en GitHub)AñadidoPlanificadoOpciones de generación de sitemap: priority, changefreq, PDF, imágenes de CDN, archivos#1444
por segmento
#1444 (incidencia en GitHub)- AñadidoPlanificadoCertificados de CA personalizados de confianza para el tráfico rastreado#1442 (incidencia en GitHub)
- AñadidoPlanificadoTratar los hostnames de CDN y espejos como alcance interno#1441 (incidencia en GitHub)
- AñadidoPlanificadoMotor de reescritura de URL para el alcance del rastreo#1440 (incidencia en GitHub)
- AñadidoPlanificadoSustitución personalizada de robots.txt para un rastreo#1439 (incidencia en GitHub)
- AñadidoPlanificadoPolítica configurable de aceptación de cookies en los rastreos#1438 (incidencia en GitHub)
AñadidoPlanificadoDescubrimiento a partir de destinos de anotaciones (canonical, hreflang, AMP, meta#1436
refresh, iframes)
#1436 (incidencia en GitHub)- AñadidoPlanificadoRastrear y auditar elementos multimedia (video, audio, source)#1435 (incidencia en GitHub)
- AñadidoPlanificadoRecopilación local de Lighthouse para una muestra de URL renderizadas#1430 (incidencia en GitHub)
AñadidoPlanificadocontrol/rate-and-load: separar los 5xx provocados por la tasa de peticiones de los#1366
403/429 de protección anti-bots en el paso «antes de culpar al sitio»
#1366 (incidencia en GitHub)AñadidoPlanificadorobots-check reporta «sin robots.txt (rastreo permitido)» cuando robots.txt devuelve 403#1364
desde un WAF
#1364 (incidencia en GitHub)AñadidoPlanificadoEl cliente HTTP recibe 403 en cada petición a una tienda Shopify tras Cloudflare que#1363
responde 200 a curl
#1363 (incidencia en GitHub)- AñadidoPlanificadoLive crawl speed control: change rate and threads during a running scan#1360 (incidencia en GitHub)
AñadidoPlanificadoCore: aspectos a pulir detectados al incorporar proyectos reales (competidores, logs,#1359
límites de rastreo, archivo)
#1359 (incidencia en GitHub)
Análisis y campos de datos
Legibilidad, vectores y rasgos semánticos, campos por URL, cobertura de comprobaciones, resúmenes (épica #1521)
- AñadidoPlanificadoConsolidar varias exportaciones de hojas de cálculo en un único libro#1528 (incidencia en GitHub)
AñadidoPlanificadoHallazgos de accesibilidad con selección de nivel WCAG y taxonomía de severidad por#1526
impacto
#1526 (incidencia en GitHub)- AñadidoPlanificadoRegistrar el atributo SameSite de cada cookie observada#1519 (incidencia en GitHub)
- AñadidoPlanificadoExtracción personalizada multimotor con estado de validación#1513 (incidencia en GitHub)
- AñadidoPlanificadoReglas de recálculo en vivo para las estadísticas de auditoría#1511 (incidencia en GitHub)
- AñadidoPlanificadoPuntuación de enlaces internos como métrica opcional posterior al rastreo#1510 (incidencia en GitHub)
- AñadidoPlanificadoExportación de la tabla de auditoría acorde con el modo de comparación visible#1509 (incidencia en GitHub)
- AñadidoPlanificadoDesglose de la auditoría por segmento con gráficos de severidad#1508 (incidencia en GitHub)
- AñadidoPlanificadoPanel de guía por hallazgo con copiado y enlaces externos#1507 (incidencia en GitHub)
- AñadidoPlanificadoDiferencia de hallazgos entre dos escaneos con color de mejora#1506 (incidencia en GitHub)
- AñadidoPlanificadoOrden predeterminado de los hallazgos de auditoría por prioridad#1504 (incidencia en GitHub)
- AñadidoPlanificadoRecuentos del resumen de auditoría con filtro por tipo#1503 (incidencia en GitHub)
- AñadidoPlanificadoTaxonomía de severidad de doble eje para los hallazgos de auditoría#1502 (incidencia en GitHub)
- AñadidoPlanificadoErrores de la consola de JavaScript como hallazgos de página#1487 (incidencia en GitHub)
- AñadidoPlanificadoMostrar la regla de robots.txt que coincide con cada URL bloqueada#1456 (incidencia en GitHub)
- AñadidoPlanificadoExtraer anotaciones hreflang de cabeceras HTTP Link y sitemaps XML#1455 (incidencia en GitHub)
- AñadidoPlanificadoPorcentaje de similitud de pares de casi duplicados y diferencias resaltadas#1454 (incidencia en GitHub)
- AñadidoPlanificadoAuditoría del inventario de cookies con resumen de propias y de terceros#1453 (incidencia en GitHub)
- AñadidoPlanificadoSeguimiento de meta keywords duplicadas y múltiples entre páginas#1452 (incidencia en GitHub)
- AñadidoPlanificadoRecopilar imágenes de fondo CSS como evidencia de imágenes#1451 (incidencia en GitHub)
- AñadidoPlanificadoHallazgos para cadenas de redirección que terminan en error de cliente o de servidor#1450 (incidencia en GitHub)
- AñadidoPlanificadoPoblación de análisis configurable para evaluar duplicados e incidencias#1449 (incidencia en GitHub)
- AñadidoPlanificadoExtraer y auditar propiedades y enlaces de documentos PDF#1448 (incidencia en GitHub)
- AñadidoPlanificadoAnálisis de frecuencia de n-gramas sobre el contenido rastreado#1431 (incidencia en GitHub)
- AñadidoPlanificadoEnlaces internos y texto del cuerpo solo renderizados como hallazgos de primera clase#1429 (incidencia en GitHub)
- AñadidoPlanificadoAñadir comprobaciones de archivos JS y CSS externos rotos o bloqueados por robots.txt#1427 (incidencia en GitHub)
- AñadidoPlanificadoAñadir una comprobación de exceso de archivos JS y CSS por página#1426 (incidencia en GitHub)
- AñadidoPlanificadoAñadir una comprobación de discrepancia entre el idioma de hreflang y el lang de html#1425 (incidencia en GitHub)
- AñadidoPlanificadoAñadir a los escaneos hallazgos de variantes www y http de la página principal#1423 (incidencia en GitHub)
- AñadidoPlanificadoAñadir a los escaneos hallazgos de presencia y formato de llms.txt#1422 (incidencia en GitHub)
- AñadidoPlanificadoReportar un sitemap.xml no válido como hallazgo del escaneo#1420 (incidencia en GitHub)
- AñadidoPlanificadoReportar un robots.txt no válido como hallazgo del escaneo#1419 (incidencia en GitHub)
AñadidoPlanificadoAñadir una sonda TLS: caducidad del certificado, discrepancia de nombre de host, versión#1418
de protocolo, cifrados débiles
#1418 (incidencia en GitHub)- AñadidoPlanificadoAñadir una comprobación de recursos no HTML enlazados como enlaces de página normales#1417 (incidencia en GitHub)
- AñadidoPlanificadoAñadir una comprobación de páginas con un único enlace interno entrante#1416 (incidencia en GitHub)
- AñadidoPlanificadoGuardar los enlaces externos con rel y añadir EXTERNAL_NOFOLLOW#1415 (incidencia en GitHub)
CorregidoPlanificadoLas cabeceras de seguridad y HSTS se evalúan solo en la respuesta final; los saltos de#1414
redirección y el host www nunca se comprueban
#1414 (incidencia en GitHub)CorregidoPlanificadoLas reglas de resultado enriquecido de SoftwareApplication son demasiado laxas; verificar#1413
que se muestren los errores de datos estructurados de la home
#1413 (incidencia en GitHub)- CorregidoPlanificadoLOW_TEXT_RATIO se dispara en casi todas las páginas; recalibrar la medida y el umbral#1412 (incidencia en GitHub)
CorregidoPlanificadoLos hallazgos agrupados informan un recuento de 1 y faltan en las consultas de hallazgos#1411
por URL
#1411 (incidencia en GitHub)AñadidoPlanificadosite-audit genera hallazgos de página para una respuesta de error en lugar de marcar la#1365
página como no auditada
#1365 (incidencia en GitHub)
Proyectos y flujos
Flujos del propietario: tareas, exportaciones, informes programados y su entrega (épica #1314)
- AñadidoPlanificadoEnvío por correo de los informes programados del monitor#1531 (incidencia en GitHub)
Cambio de marca
Renombrado seohead → spiderhead: CLI, paquete, entorno, documentación (#1523)
AñadidoPlanificadoRenombrar el binario de la CLI, el paquete y el prefijo de variables de entorno de#1523
seohead a spiderhead
#1523 (incidencia en GitHub)
Interfaces CLI y MCP
Mensajes de error claros, ayuda real, salidas de lectura acotadas, transportes MCP (épicas #1410 #1421)
- AñadidoPlanificadoServidor MCP como modo de primera clase de la CLI con transportes stdio y streamable HTTP#1525 (incidencia en GitHub)
- CorregidoPlanificadoMostrar la subayuda real de 'seohead sf' en lugar de un marcador de argumentos reenviados#1406 (incidencia en GitHub)
Capa de IA
Destinos de prompt por elemento SEO sobre seo_ai_column, sin depender del proveedor (#1524)
AñadidoPlanificadoAnálisis de páginas asistido por IA con objetivos de prompt configurables sobre los datos#1524
del rastreo
#1524 (incidencia en GitHub)
Calidad de ingeniería
División en módulos de los archivos gigantes y dirección de dependencias (#1514 #1515)
AñadidoPlanificadoDirección de dependencias: eliminar las inversiones de importación del core hacia las#1515
funciones
#1515 (incidencia en GitHub)- AñadidoPlanificadoDividir los módulos de adaptadores y motores demasiado grandes en unidades cohesivas#1514 (incidencia en GitHub)
Distribution: installers & one-command install
Sales-readiness theme: native installers per OS, our own package name, and a one-command CLI install. Being ready to ship is the point of this milestone.
- AñadidoPlanificadoOwn command name with a one-command install (pipx/brew) for the CLI#1557 (incidencia en GitHub)
- AñadidoPlanificadoShip native installers: DMG (macOS), Linux (AppImage/deb), Windows installer#1556 (incidencia en GitHub)
3.1.0
Primera versión etiquetada tras el cambio de nombre desde SEOHEAD Tools11 de octubre de 2026455 entradas · Primera versión etiquetada tras el cambio de nombre desde SEOHEAD Tools138 añadido275 cambiado42 corregido
11 de octubre de 2026
5 añadido54 cambiado2 corregidoCambiadoFuncionaRehace Project settings (Schedule y Crawl) con componentes nativos de lienzo compartidos,#1323
fuentes Roboto sin conexión…
Rehace Project settings (Schedule y Crawl) con componentes nativos de lienzo compartidos, fuentes Roboto y Material Symbols sin conexión, y un diseño de una sola columna a 800 px.
#1323 (incidencia en GitHub)CambiadoFuncionaUsa inglés en toda la interfaz de la aplicación, conserva el comando de programación#1323
existente y los contratos de documentos, y muestra solo datos de programación respaldados por el núcleo.
#1323 (incidencia en GitHub)CambiadoFuncionaConserva las identidades y alias de los espacios de trabajo mientras Project settings#1323
está abierto; impide guardados duplicados…
Conserva las identidades y alias de los espacios de trabajo mientras Project settings está abierto, e impide guardados duplicados mientras el núcleo responde.
#1323 (incidencia en GitHub)CambiadoFuncionaEscritorio: los ajustes del proyecto ganan una pestaña Schedule (días laborables, días#1322
del mes, ventana de ejecución, zona horaria…
Los ajustes del proyecto de escritorio ganan una pestaña Schedule (días laborables, días del mes, ventana de ejecución, zona horaria, competidores) y una pestaña Crawl (modo de rastreo, preajuste o cadena personalizada de User-Agent, pausa entre solicitudes, presupuesto de URL, SpiderHeadBot o un user agent personalizado); ambas leen y escriben el proyecto a través del núcleo, y la vista general del proyecto muestra la próxima y la última ejecución programada. Un modo --tray ejecuta los escaneos vencidos del núcleo y mantiene el Mac despierto solo mientras se ejecuta un escaneo.
#1322 (incidencia en GitHub)CambiadoFuncionaAnálisis programados del proyecto (#1322, núcleo):
schedule.jsonen el directorio del#1322proyecto guarda la programación: días laborables y/o días del mes, una ventana horaria en la zona horaria del sitio, activar o desactivar, competidores, modo de rastreo
#1322 (incidencia en GitHub)spider/sitemap/list, presupuestos de URL y de peticiones por ejecución, pausa de cortesía y modo por tramos, que reanuda el rastreo parcial anterior. Se edita conschedule-set/seo_schedule_setyexpected_revision, yschedule-showmuestra la última ejecución y la siguiente ventana prevista.schedule-run-duees un punto de entrada sin interfaz que ejecuta solo los análisis vencidos, rechaza el solapamiento mediante un bloqueo (lease) y registra cada decisión en el diario del proyecto.schedule-installyschedule-uninstallescriben o eliminan un plist de launchd, una línea de cron o un comando del Programador de tareas solo cuando se invocan de forma explícita.CambiadoFuncionaUser agents de rastreo (#1322): perfiles (
spiderhead,googlebot,googlebot-desktop…#1322User agents de rastreo (#1322): perfiles predefinidos (
#1322 (incidencia en GitHub)spiderhead,googlebot,googlebot-desktop,googlebot-smartphone,bingbot,yandexbot,yandexmobilebot,baiduspider,duckduckbot,applebot,gptbot,claudebot,perplexitybot, además de navegadores de escritorio y móviles) o una cadena personalizada. El valor por defecto es ahoraSpiderHeadBot/<version> (+https://github.com/PavloSEO/spiderhead), y la coincidencia de grupos en robots.txt usa la misma identidad. Los sitios que coincidían con el grupo robots deSEOHEAD-Toolsdeben nombrarSpiderHeadBoten sus reglas.CambiadoFuncionaUn análisis guardado del proyecto ahora marca los elementos automáticos de la lista de#1314
comprobación que midió.
Cada elemento de comprobación activado se resuelve en uno de tres resultados:
#1314 (incidencia en GitHub)succeeded, cuando la auditoría guardada ejecutó la comprobación y el análisis sirve de evidencia;unavailable, cuando el rastreo la omitió o la desactivó, conservando su motivo; ounmeasured, cuando la auditoría no menciona la comprobación. Un elemento no medido conserva su registro anterior y se informa por nombre enchecklist_evidence, así que nunca cuenta como 0. Un rastreo que falla o se interrumpe marca sus comprobaciones automáticas comofailedcon el motivo del fallo. El mismo camino de registro sirve ahora también al flujoprepare, que antes tenía su propia copia del bucle. Un proyecto cuya lista de comprobación no está inicializada se omite, con el motivo indicado.CambiadoFuncionaLos espacios de competidores conservan la URL tal como se introdujo: el rastreo de un#1314
competidor parte de su URL
#1314 (incidencia en GitHub)wwwen lugar del dominio desnudo, y un rastreo de la URL de un competidor ya no marca los elementos de la lista de comprobación del propietario; el resultado se registra solo en el espacio del propio competidor. Al abrir un proyecto con un espacio de competidor dañado, ese competidor se informa como no disponible en lugar de hacer fallar la operación.CambiadoFuncionaLos candidatos a competidor se pueden registrar, listar y eliminar desde la CLI#1314
(
#1314 (incidencia en GitHub)project-competitors-add,project-competitors-list,project-competitors-remove) y con las herramientas MCPseo_project_competitors_*correspondientes. Cada candidato conserva la URL tal como se introdujo, incluido un hostwww, y los hosts con y sin www cuentan como el mismo sitio en las comprobaciones de duplicados. Un competidor con hostwwwya no rompe la preparación ni hace queproject-observefalle.CambiadoFunciona
--max-urlses ahora el presupuesto de páginas del rastreo: un presupuesto explícito#1314completa los presupuestos de peticiones y de tiempo que no estén definidos…
#1314 (incidencia en GitHub)--max-urlses ahora el presupuesto de páginas del rastreo: un presupuesto explícito de páginas completa los presupuestos de peticiones y de tiempo que no estén definidos (3 peticiones y 2 segundos por página), de modo que los rastreos de 50 a 300 páginas se admiten sinapprove_large_crawl. Los presupuestos por encima de los umbrales del proyecto siguen rechazándose.CambiadoFuncionaUna parada deliberada por presupuesto de URL se guarda como captura terminada con#1314
finish_reason…Una parada deliberada por presupuesto de URL se guarda como captura terminada, con
#1314 (incidencia en GitHub)finish_reasonstopped_by_budgety una horafinished_at, en lugar deinterruptedsin hora de fin. Sus URL en cola siguen disponibles para reanudar el rastreo.CambiadoFuncionaLas URL de competidores conservan el host tal como se introdujo (por ejemplo,
www.se#1314mantiene), en lugar de guardarse sin él.
#1314 (incidencia en GitHub)CambiadoFuncionaLa aplicación de escritorio añade sitios de competidores desde el portapapeles o uno a#1314
uno a través del núcleo, fija un límite de URL por sitio e inicia sus análisis en paralelo. Un competidor aparece como analizado solo después de un análisis conservado y terminado.
#1314 (incidencia en GitHub)CambiadoFuncionaLos análisis nativos miden HSTS, contenido mixto y datos estructurados a partir de su#1314
propia evidencia guardada, así que una exportación de SF ausente o desactualizada ya no los marca como ausentes.
#1314 (incidencia en GitHub)duplicate-checkmarca como no medida una ejecución con cero pares comparados. Las incidencias de plantilla en todo el sitio (mismo encabezado de la plantilla común, ratio bajo de texto) son ahora una sola incidencia con el número de páginas (#1314).CambiadoFuncionaAceptar un objetivo del propietario añade solo la tarea de comprobación de ese objetivo.#1314
Ya no reconcilia todo el catálogo integrado en
#1314 (incidencia en GitHub)coverage.json; las filas integradas se añaden bajo demanda cuando se toca alguna.CambiadoFuncionaUna lista de comprobación ocupada nombra al titular activo (por ejemplo, un rastreo#1314
nativo en marcha y su pid) en lugar de llamar residuo al bloqueo. El bloqueo registra el pid de quien escribe; un bloqueo sin titular activo sigue informándose como residuo.
#1314 (incidencia en GitHub)CambiadoFuncionaUna ejecución de flujo bloqueada por un paso fallido, no disponible, omitido o#1314
interrumpido sigue siendo reanudable, y un paso pendiente posterior puede guardarse como punto de control aunque sobrepase un paso que no tuvo éxito. Los pasos siguen debiendo registrarse como punto de control en el orden registrado, y una ejecución interrumpida sigue rechazando nuevos pasos.
#1314 (incidencia en GitHub)CambiadoFuncionaUna revisión registrada por un agente ya no marca como completado para el propietario un#1314
elemento manual o entregable.
El elemento sigue pendiente de la aprobación del propietario o de un revisor que no sea agente.
#1314 (incidencia en GitHub)CambiadoFuncionaLas referencias de la bandeja de entrada aceptan ids de objetivo (
inbox:<uuid>), para#1314que una nota pueda citar el objetivo al que se refiere.
#1314 (incidencia en GitHub)CambiadoFuncionaLos elementos de la lista de comprobación que nunca se intentaron y son manuales muestran#1314
el estado
#1314 (incidencia en GitHub)not_runen lugar dereview; solo un intento pendiente de decisión permanece enreview.CambiadoFuncionaEl modelo de lectura de Issues (evidencia de las incidencias de
observe) informa de#1314recuentos por comprobación (
#1314 (incidencia en GitHub)by_check) y de unnext_offsettras las primeras 20 incidencias;findings_pagepagina el resto.CambiadoFuncionaComprobaciones nativas del rastreo (#1314): el tamaño de imagen (
IMG_OVER_KB) se mide#1314ahora a partir de las descargas de imágenes propias del rastreo, y el estado del sitemap (
#1314 (incidencia en GitHub)SITEMAP_URL_4XX_5XX,SITEMAP_URL_3XX,SITEMAP_URL_NON_INDEXABLE) a partir de la descarga propia de cada URL listada en el sitemap. Una URL listada que el rastreo nunca solicitó se cuenta como no medida, nunca como correcta.IMG_MISSING_ALT,IMG_MISSING_DIMENSIONSyHREFLANG_ERRORindican en un análisis nativo que el rastreo no los mide tal como los define la exportación de SF, en lugar de apuntar a un filtro de SF. La falta de evidencia de hreflang y de contenido mixto en un análisis nativo se informa como no medida por el rastreo nativo, no como una exportación ausente.CambiadoFuncionaDiario del proyecto (#1314): cada evento del proyecto se escribe ahora también como una#1314
viñeta en log.md…
Diario del proyecto (#1314): cada evento del proyecto se escribe ahora también como una viñeta en
#1314 (incidencia en GitHub)log.md, y el núcleo registra entradas automáticas para los rastreos terminados (scans), los informes de proyecto generados y los intentos de la lista de comprobación (agent). Las entradas van aevents.jsonly las leeproject-event-page. Los hooks automáticos nunca hacen fallar el rastreo, el informe o el paso de la lista que describen.project-event-appendyseo_project_event_appendmantienen su interfaz y añaden la línea enlog.md.CambiadoFuncionaEl rastreo nativo ahora guarda las cabeceras de seguridad que leen las comprobaciones#1314
(
#1314 (incidencia en GitHub)Strict-Transport-Security,Content-Security-Policy,X-Frame-Options,X-Content-Type-Options,Referrer-Policy,Permissions-Policy). Antes se descartaban al capturar, así que un sitio que enviaba HSTS se informaba como si no lo tuviera. Las cabeceras Set-Cookie solo guardan sus flags (secure,httponly,samesite=), nunca el nombre ni el valor de la cookie. Una cabecera de seguridad enviada más de una vez en la misma página se informa comoDUPLICATE_SECURITY_HEADER.CambiadoFunciona
workflow-startnecesita solo un objetivo del propietario aceptado:--goal-id(o#1314context.goal_id)…
#1314 (incidencia en GitHub)workflow-startnecesita solo un objetivo del propietario aceptado: basta con--goal-id(ocontext.goal_id). El prompt registrado usa por defectoskill:workflow/full-audit-v1, y la tarea de la lista de comprobación usa por defecto la que creó la aceptación del objetivo (custom:goal-<entry>). Los rechazos indican el comando del propietario que corrige el vínculo que falta. Las opciones están documentadas enseohead workflow-start --help.CambiadoFuncionaLas poblaciones de la lista de comprobación aceptan objetos parciales: solo
kindy#1314
#1314 (incidencia en GitHub)sourceson obligatorios, y el resto de claves quedan sin definir por defecto. Una población rechazada indica sus claves ausentes o desconocidas.CambiadoFuncionaLos rastreos nativos del proyecto recurren al
/sitemap.xmldel origen cuando robots.txt#1314declara…
Los rastreos nativos del proyecto recurren al
#1314 (incidencia en GitHub)/sitemap.xmldel origen cuando robots.txt no declara ningún sitemap. Si esa alternativa no existe, se registra como incompleta, pero no interrumpe el rastreo.CambiadoFuncionaLos logs del servidor conservan ahora los totales exactos de IP de bots en disco en lugar#1311
de una muestra limitada, con registros por IP acotados, visitas, última visita y filtros por subred. La verificación DNS explícita comprueba cada IP seleccionada por separado, registra la evidencia PTR y de resolución directa, admite IPv6 y conserva los resultados no disponibles o de tiempo agotado como no comprobados. Las cachés locales caducan a la hora; las lecturas nunca disparan consultas DNS.
#1311 (incidencia en GitHub)AñadidoFuncionaAñadidos importar logs locales del proyecto, resumen paginado, evidencia de bots y cruce#1311
con análisis nativos…
Añadidos importar logs locales del proyecto, resumen paginado, evidencia de bots y comandos de cruce con el análisis nativo, a través de los mismos manejadores de CLI y MCP. Los artefactos de log separados conservan particiones por fecha y la cobertura y procedencia de cada fuente, sin cambiar los esquemas congelados de los análisis. Si falta evidencia o está incompleta, no se emiten conclusiones de ausencia. Las pantallas de logs del escritorio quedan como una tarea de presentación aparte.
#1311 (incidencia en GitHub)CambiadoFuncionaControlar las llamadas de producción a DataForSEO de Google antes de construir el#1310
cliente, mostrar cotizaciones offline…
Las llamadas de producción a DataForSEO de Google se controlan antes de construir el cliente, muestran cotizaciones offline a partir de los precios del proveedor proporcionados, tienen en cuenta la profundidad de SERP y los cargos por operadores de búsqueda, y aplican los techos conocidos en USD por llamada antes del transporte. Amplía las operaciones acotadas de índice de backlinks y registra los costes ausentes o las formas de respuesta mal formadas como recibos inciertos. Los límites de moneda por proyecto y por mes siguen pendientes de una decisión del propietario.
#1310 (incidencia en GitHub)CambiadoFuncionaFusionar la evidencia explícita de origen e importación de backlinks en instantáneas de#1310
historial locales privadas con…
Fusiona la evidencia explícita de origen e importación de backlinks en instantáneas de historial locales privadas, con observaciones completas de tokens rel, anclas, dominios de referencia, filtros y señales transparentes de revisión de spam. Añade rutas CLI/MCP de perfil y de exportación revisada de disavow, sin envíos automáticos.
#1310 (incidencia en GitHub)AñadidoFuncionaAñade avisos de revisión por tokens rel mixtos y por divulgación de patrocinio saliente,#1310
a partir de la evidencia nativa conservada. Conserva el contexto no disponible, los recuentos nulos para poblaciones de HTML sin analizar por completo y las clases sponsored, ugc y nofollow en los informes y en las comprobaciones de donantes, sin cambiar el esquema congelado de análisis conservados.
#1310 (incidencia en GitHub)CambiadoFuncionaLas comprobaciones nativas de DOM y de duplicados leen ahora el documento conservado#1307
seleccionado de cada página por URL exacta, con linaje verificado de respuesta y cuerpo. La retención desactivada, los cuerpos ausentes, no válidos o que superan el presupuesto siguen siendo omisiones explícitas, y las incidencias parciales llevan cobertura. Los hashes exactos del área de contenido y las incidencias SimHash/LSH acotadas se guardan en la auditoría nativa sin necesidad de un directorio HTML de SF. Las bandas LSH adaptadas al umbral preservan la recuperación de los pares que cumplen el criterio mientras reducen los cubos de candidatos amplios; el agotamiento del presupuesto de análisis de similitud no descarta los hashes exactos.
#1307 (incidencia en GitHub)CambiadoFuncionaLas auditorías SF ejecutan opcionalmente similitud semántica y revisión de title/H1#1307
frente al cuerpo conservado, con un adaptador local indicado de forma explícita o con embeddings declarados. No se selecciona automáticamente ningún modelo ni proveedor. La identidad del adaptador, los hashes de origen, las puntuaciones, los límites y las omisiones acompañan a los candidatos de revisión. La similitud semántica no afirma contenido duplicado, relevancia de consulta ni canibalización. Las dos filas de cobertura semántica de SF siguen como huecos hasta que se seleccione y valide un adaptador real. La autorización de un proveedor externo exige el booleano literal
#1307 (incidencia en GitHub)true; las cadenas o los enteros que solo parecen verdaderos nunca autorizan una llamada de embeddings.CambiadoFuncionaLas auditorías nativas conservadas agrupan ahora los enlaces internos rotos por destino#1306
observado, con evidencia de origen y de texto ancla; registran cadenas y bucles de redirección con el estado de cada salto; distinguen la búsqueda interna por ruta y los anclas vacías, y muestran los resultados capturados de externos sin respuesta. Las incidencias de consistencia de sitemap y robots usan la pertenencia y la evidencia de respuesta conservadas, sin nuevas descargas en vivo; la evidencia ausente o parcial sigue siendo explícita.
#1306 (incidencia en GitHub)AñadidoFuncionaAñade un grafo acotado de enlaces de análisis guardados con filtros de posición, sección#1306
y vecindario local…
Añade un grafo acotado de enlaces de análisis guardados, con filtros de posición, sección y vecindario local, agregación por sección y cambios de aristas entre análisis. El reanálisis offline completa las posiciones con lotes derivados reanudables e informa de la evidencia sin clasificar en la inspección de enlaces y en el estado del análisis, preservando el esquema congelado scan.v1.
#1306 (incidencia en GitHub)AñadidoFuncionaAñade generación local de sitemap XML a partir de páginas 200 canónicas e indexables#1306
conservadas, con lastmod observado, exclusiones, división por protocolo, índice de sitemap y sitemap de imágenes opcional. La CLI y el MCP comparten las mismas implementaciones; la publicación de la salida exige un directorio local nuevo y nunca despliega archivos.
#1306 (incidencia en GitHub)CambiadoFuncionaConserva los objetivos de descubrimiento ausentes en el momento de la captura cuando un#1306
procesamiento posterior de sitemap o de semillas (seed) añade la URL…
Conserva los objetivos de descubrimiento ausentes en el momento de la captura cuando un procesamiento posterior de sitemap o de semillas añade la URL al catálogo conservado. La evidencia explicada de no resueltos o excluidos sigue siendo inmutable, mientras que los objetivos conocidos reclamados y las discrepancias de identidad no nulas siguen siendo inválidos.
#1306 (incidencia en GitHub)CambiadoFuncionaLa generación de sitemap de imágenes excluye las respuestas de recurso no 200 conocidas,#1306
aunque el recurso no se haya guardado como página rastreada, y marca las respuestas de imagen no medidas como cobertura parcial.
#1306 (incidencia en GitHub)CambiadoFuncionaConserva los atributos canonical y de paginación brutos como contexto versionado del#1305
documento, sin cambiar el SQL congelado del análisis. Las etiquetas canonical con atributos hreflang, lang, media o type no soportados, las anotaciones malformadas y las declaraciones entre hosts o protocolos generan ahora incidencias ligadas a la evidencia; las palabras clave de relación bien formadas pero desconocidas siguen sin clasificar.
#1305 (incidencia en GitHub)CambiadoFuncionaAmplía las sondas acotadas a objetivos del mismo host a la paginación y conserva las#1305
observaciones medidas de noindex y canonical. Las cadenas canonical nativas y las incidencias de noindex en canonical o hreflang pueden usar sondas; las sondas heredadas de solo estado siguen siendo legibles y no medidas para las directivas HTML.
#1305 (incidencia en GitHub)CambiadoFuncionaEvalúa las cadenas de paginación nativas opacas en busca de contradicciones recíprocas#1305
explícitas de next/prev, conservando las reglas numeradas o de paso y los estados sin juzgar con nombre. Selecciona las URL de incidencias guardadas, incluidos los miembros agrupados, mediante scan-url-query, con tablas SQLite temporales y evidencia audit.v2 en streaming.
#1305 (incidencia en GitHub)CorregidoFuncionaMantiene sin clasificar los tokens de relación Unicode desconocidos y con signos de#1305
puntuación, normaliza las autoridades canonical equivalentes (IDN y puerto por defecto) y conserva las rutas exactas de destino de paginación nativa. Los tokens de página mixtos ilegibles siguen sin juzgar; el defecto de paginación de la tienda se detecta incluso cuando la página uno no tiene número en su URL.
#1305 (incidencia en GitHub)CambiadoFuncionaRenderiza las anotaciones next/prev declaradas del fixture de la tienda para que su#1305
referencia de paginación D41 se sirva realmente y el rastreo nativo pueda validarla.
#1305 (incidencia en GitHub)CambiadoFuncionaConserva la evidencia estática de AMP y de accesibilidad ligada al documento en las filas#1304
de contexto de análisis existentes, respetando el esquema SQL congelado
#1304 (incidencia en GitHub)scan.v1. Las incidencias estructurales de AMP revisan el doctype original, head y body, el charset UTF-8, el viewport, el script de runtime y las declaraciones de boilerplate; los destinos AMP emparejados sin marcador de raíz AMP se identifican por separado. Las reglas completas del validador de AMP siguen sin estar disponibles a la espera de una decisión sobre la licencia.CambiadoFuncionaPrimeras incidencias de accesibilidad: idioma del documento, etiquetas de formulario,#1304
alternativas de imagen, saltos de encabezado y el landmark principal. Las incidencias conservan ejemplos acotados y recuentos completos de ocurrencias. El contraste calculado y las reglas de axe-core renderizadas siguen sin medirse.
#1304 (incidencia en GitHub)CambiadoFuncionaValida Schema.org Microdata y los sujetos y propiedades RDFa comunes con el vocabulario#1304
incluido y las reglas de resultados enriquecidos existentes. Los errores, advertencias y propiedades obligatorias ausentes conservados por URL se convierten en incidencias nativas. Las construcciones RDFa no soportadas son evidencia parcial explícita, no un resultado de validación limpio.
#1304 (incidencia en GitHub)CambiadoFuncionaSirve los árboles JSON-LD analizados junto con los errores de origen, posición y sintaxis#1304
de cada bloque en scan-structured-blocks…
Sirve los árboles JSON-LD analizados junto con los errores de origen, posición y sintaxis de cada bloque en
#1304 (incidencia en GitHub)scan-structured-blocks; limita los árboles de propiedades anchos y expone ese límite. Lee el último documento de una URL y representación solicitadas sin cambiar su análisis.CambiadoFuncionaConserva la evidencia estructurada parcial o no disponible sin ocultar los errores#1304
hermanos confirmados.
Resuelve las identidades JSON-LD soportadas frente a la misma base de documento que el marcado HTML, conservando el JSON original. Rechaza los bloques JSON escalares o vacíos como grafos válidos, y comparte la selección normalizada de etiquetas JSON-LD en vivo entre el analizador y las proyecciones servidas.
#1304 (incidencia en GitHub)CambiadoFuncionaLas auditorías nativas muestran ahora el marcado de cabecera que bloquea el renderizado a#1303
partir del HTML conservado completo, sin cambiar el esquema congelado scan.v1. Los cuerpos ausentes, incompletos o limitados por presupuesto siguen sin estar disponibles. Se reutilizan la detección existente de recursos de cabecera y la entrada de extracción personalizada de SF.
#1303 (incidencia en GitHub)AñadidoFuncionaAñade presupuestos configurables de bytes para la navegación observada nativa y para cada#1303
recurso individual, señales de entrega de caché y de fuentes, heurísticas de minificación y de scripts heredados, y duplicados exactos de scripts en la misma página, a partir de la evidencia scan.v2 conservada. Los datos no descargados y las cargas de runtime incompletas siguen siendo explícitos; las declaraciones responsive no se suman como peso de runtime. Los límites inferiores solo para HTML, los recuentos escalares de cobertura, las muestras de fuentes y los resúmenes de origen siguen siendo explícitos y acotados.
#1303 (incidencia en GitHub)CambiadoFuncionaRecoge la cobertura precisa de JS/CSS de Chromium, acotada, en los renders solicitados,#1303
conserva resúmenes de uso UTF-16…
Recoge la cobertura precisa de JS/CSS de Chromium, acotada, en los renders solicitados; conserva resúmenes de uso UTF-16 y hallazgos de dimensionado de imágenes renderizadas, y los lee al reabrir o en el reanálisis offline. Los motores no soportados y las mediciones ausentes no se convierten en resultados limpios.
#1303 (incidencia en GitHub)CambiadoFuncionaAcepta JSON de Lighthouse por URL, acotado y coincidente, para el descubrimiento de LCP,#1303
árboles de dependencias, responsables de desplazamiento de diseño, entrega de imágenes, reflow forzado y ejecución de scripts, con procedencia de la captura y hashes de entrada. No se añade ningún proceso de Lighthouse, proveedor de pago ni inferencia de CWV de campo. Se actualizan el registro, la cobertura de SF y la documentación de referencia generada.
#1303 (incidencia en GitHub)CorregidoFuncionaLos umbrales aditivos de activos quedan fuera de la cabecera congelada del análisis#1303
nativo y sus valores exactos se guardan…
Los umbrales aditivos de activos quedan fuera de la cabecera congelada del análisis nativo, y sus valores exactos se guardan en un contexto de ejecución validado y versionado. La reanudación compara estos valores por separado, y el reanálisis offline los restaura desde la evidencia conservada. Los lectores ligeros anteriores pueden seguir inspeccionando la forma, sin cambios, de la configuración de cabecera.
#1303 (incidencia en GitHub)CambiadoFunciona
recordde la lista de comprobación acepta ahora una comprobación automática con éxitocuyo análisis guardado es un audit.v2 en streaming; antes fallaba con
'NoneType' object is not subscriptable, porque la auditoría vive en el archivo auxiliar (companion) y no en la tabla heredada del análisis. Los formatos de registro aceptados están documentados enseohead project checklist-record --help, en el esquema MCPseo_project_checklist_recordy endocs/INPUTS.md.CambiadoFuncionaEjecuta la suite completa del toolkit una vez en Python 3.15, en lugar de una matriz de
versiones anteriores, conservando cuatro grupos de pruebas verificados y la cobertura combinada. Usa la misma versión estable de Python para los arranques de CI y de compilación de releases.
CambiadoFuncionaLa lista Work del escritorio lee cada página de la lista de comprobación (100 por
petición) en lugar de las primeras 50 filas. Issues muestra cada comprobación del núcleo según el registro, en lugar de mostrar «Other check».
CambiadoFuncionaDesktop Work lee cada página de la lista de comprobación, pero muestra el panel de tareas
del proyecto de una página cada vez, así que una lista de cualquier tamaño ya no falla con «at most 100 rows». Si el propietario no ha elegido ninguno, el escritorio abre el análisis que deja una auditoría completa (el análisis completo más grande), y el descubrimiento del núcleo comprueba también el propio entorno del intérprete del escritorio (
sys.prefix) antes que PATH.CambiadoFuncionaConsolida las comprobaciones de auditoría conservadas y las mejoras nativas del
escritorio.
Conserva los ajustes de presupuesto de recursos sin cambiar la cabecera congelada del análisis, mantiene el reanálisis offline seguro y la reanudación, y comparte los componentes nativos de ajustes del proyecto, los tokens de tema y las fuentes incluidas. Elimina los insumos de diseño privados del árbol distribuido.
CambiadoFuncionaVincula las revalidaciones de remediación a la política de activos efectiva validada,
conservando la cabecera original del análisis y los bytes de origen.
CambiadoFuncionaLa cobertura de la lista de comprobación del proyecto ahora vincula los informes audit.v2
en streaming:
report-build --projectyaudit-workflow --action reportadjuntan la instantánea de la lista a la salida xlsx, docx, csv, md y PDF, en lugar de generar un informe sin vincular. Un análisis detenido por su presupuesto de URL (stopped_by_budget) se acepta como la última auditoría del proyecto, y su informe declara el alcance limitado.report-build --inputacepta la claveformat.report-build --project --format jsonsobre una auditoría en streaming se rechaza con una explicación, porque el JSON se escribe tal cual y no puede llevar la instantánea de la lista.
10 de octubre de 2026
16 añadido51 cambiadoCambiadoFuncionaEl monitor de análisis del escritorio sigue el tablero de diseño de ScanRun: porcentaje#1203
real a partir de los contadores fetched/found, una barra de progreso de 10 px, el límite de frecuencia del recolector y un marcador de posición honesto de 120 px para el gráfico de velocidad (el historial de velocidad del núcleo se sigue en #1203).
#1203 (incidencia en GitHub)CambiadoFunciona
check_sampleenseohead/checks/custom_extract.pyejecuta extractores CSS, XPath y#1059regex…
#1059 (incidencia en GitHub)check_sampleenseohead/checks/custom_extract.pyejecuta los extractores CSS, XPath y regex sobre un único documento HTML guardado, sin análisis ni petición de red. Cada resultado incluye sus valores y unreasonpara un resultado vacío (no_match,empty_htmlobudget_exceeded), de modo que una respuesta vacía nunca se presenta como un resultado limpio (#1059). Es solo una llamada del núcleo: todavía no hay ninguna herramienta CLI ni MCP registrada, y obtener una URL en vivo está deliberadamente excluido.CambiadoFuncionaLa comprobación de secuencia de paginación (
PAGINATION_SEQUENCE_ERROR) evalúa ahora las#1057series con paso: cuando un paso cubre la mayoría de los pasos de una serie, se informa de la ruptura de ese paso (
#1057 (incidencia en GitHub)?page=1,3,5,8se rompe al pasar de 5 a 8). Los esquemas de desplazamiento irregulares y las series sin números siguen sin evaluarse y se nombran como omitidos.AñadidoFuncionaNueva comprobación de rastreo
INTERNAL_NOFOLLOW_OUTLINKS(aviso): indica cada página de#1052origen que contiene enlaces salientes internos con
#1052 (incidencia en GitHub)nofollow, con su número y una muestra acotada de destinos. Cubre el hueco a nivel de página de la fila «Internal Nofollow Outlinks» de Screaming Frog, que estaba comopartial. Se ejecuta en los rastreos nativos y se omite por nombre en las ejecuciones solo de exportación y en las de lista de URL.CambiadoFuncionaEl parser lee
<link rel="alternate">con calificador de medios y sinhreflang(una#1051URL…
El parser lee las declaraciones
#1051 (incidencia en GitHub)<link rel="alternate">con calificador de medios y sinhreflang(una URL móvil independiente) enparse_htmlcomomobile_alternates(#1051). La comprobaciónMobile Alternate Linkde SF sigue pendiente; la que compara el canonical de la URL móvil todavía no está escrita.AñadidoFuncionaAñade la comprobación
HREFLANG_UNLINKED_TARGET(advertencia): un destino de alternativa#1050hreflang…
Añade la comprobación
#1050 (incidencia en GitHub)HREFLANG_UNLINKED_TARGET(advertencia): se informa de cada destino de alternativa hreflang al que ningún enlace normal del rastreo apunta. Así queda cubierta la incidencia «Unlinked Hreflang URLs» de Screaming Frog. La comprobación lee la exportación All Hreflang y la columna Internal:All Inlinks, igual queUNLINKED_CANONICAL; una autorreferencia no cuenta, y un rastreo parcial no emite la incidencia. El registro pasa de 182 a 183 comprobaciones.CambiadoFuncionaDimensionado de imágenes en rutas renderizadas: render-check ahora registra el tamaño#1049
intrínseco en píxeles de cada imagen frente a su caja renderizada y a la relación de píxeles del dispositivo (
#1049 (incidencia en GitHub)image_sizing: evidencia de sobredimensionado y de ampliación). Es solo evidencia; todavía no hay id de comprobación de SF-analyzer, así que «Incorrectly Sized Images» pasa de «gap» a «partial» (#1049).CambiadoFuncionaSemantically Similar: el estado sigue en
gapy la nota ahora indica el bloqueo.#1041El comando y la herramienta MCP de similitud semántica existen, pero no se incluye ningún adaptador de embeddings y la ejecución de SF todavía no llama al módulo (#1041).
#1041 (incidencia en GitHub)AñadidoFuncionaAñade la comprobación
INTERNAL_LINK_SPONSORED_UGC(aviso): un enlace del mismo sitio#1040que lleva…
Añade la comprobación
#1040 (incidencia en GitHub)INTERNAL_LINK_SPONSORED_UGC(aviso): un enlace del mismo sitio conrel="sponsored"orel="ugc"se informa con el conjunto completo de tokens de rel. Necesitalink_attributes.capture, como las demás comprobaciones basadas en rel, y sin ese ajuste se informa como no medido.AñadidoFuncionaAñade la base de la generación de sitemaps XML a partir de un escaneo conservado:#1039
select_indexablemantiene…Añade la base de la generación de sitemaps XML a partir de un escaneo conservado:
#1039 (incidencia en GitHub)select_indexableconserva solo las páginas HTML 200 autocanónicas, nonoindexy no bloqueadas por robots, e indica el motivo de cada URL excluida;render_sitemapsescribe un<urlset>, o bien archivos divididos más un<sitemapindex>cada 50 000 URL o 52 428 800 bytes por archivo. La exposición en CLI y MCP llega después.AñadidoFuncionaAñade
cloudflare-traffic(CLI) yseo_cloudflare_traffic(MCP): una fuente de solo#1026lectura de Cloudflare GraphQL Analytics para el analizador de logs cuando faltan los logs del origen (#1026, #1009). Devuelve bots × URL × códigos de estado × estado de caché por día, con la misma estructura que
#1026 (incidencia en GitHub)log-analyze, y se etiqueta comosource: cloudflare-aggregatedporque son datos agregados de borde, no logs sin procesar (no hay IP de cliente, así que no se puede verificar el DNS inverso). Los días que llenan el límite de 10 000 filas de la página se dividen por ventanas de tiempo; la llamada se registra en el libro de gasto como proveedor gratuito. El token procede deCLOUDFLARE_API_TOKENo deSEOHEAD_CLOUDFLARE_TOKEN_FILEy nunca se muestra.CambiadoFuncionaEvaluador interno de incidencias de Search Console, todavía sin conectar a los informes:#1025
#1025 (incidencia en GitHub)seohead/checks/search_console_findings.pycruza las páginas del rastreo con un documento GSC normalizado y evalúa GSC_ORPHAN, NO_SEARCH_DATA y NON_INDEXABLE_WITH_SEARCH_DATA. Una comprobación se omite indicando su motivo cuando el rastreo es parcial, la ventana está incompleta, la recopilación es una muestra o está truncada, o no se aporta evidencia; una comprobación omitida nunca se informa como limpia.CambiadoFunciona
crawl-enrichinforma de cuatro incidencias de analítica web a partir de un CSV sin#1024conexión con la URL como clave: URL huérfanas de analítica, páginas indexables sin datos de analítica, páginas no indexables con visitas y tasa de rebote superior al 70 %. Los parámetros
#1024 (incidencia en GitHub)--visits-columny--bounce-columneligen los datos; si falta una columna, se rechaza indicando su nombre; los valores ilegibles se cuentan y nunca se toman como cero, y las URL huérfanas de analítica no se informan en un rastreo parcial. La obtención en vivo por URL desde Metrika o GA4 todavía no está incluida (#990, #984).CambiadoFuncionaEl mapa de cobertura de incidencias de SF incluye las cuatro de analítica web (Orphan#1024
URLs…
El mapa de cobertura de incidencias de SF pasa a incluir las cuatro de analítica web («Orphan URLs», «Bounce Rate Above 70%», «No GA Data», «Non-Indexable with GA Data») como detectadas por
#1024 (incidencia en GitHub)crawl-enricha partir de un CSV sin conexión, en lugar de fuera de alcance.sf runtodavía no las emite.CambiadoFuncionaNúcleo de cobertura de laboratorio para CSS y JavaScript sin usar (#1023, primera#1023
entrega): un analizador puro recibe las cargas de
#1023 (incidencia en GitHub)page.coveragede Playwright e informa de los caracteres sin usar por recurso, con una incidencia cuando un recurso está en gran parte sin usar y es grande. Recopilar la cobertura desde una página renderizada es la siguiente entrega.CambiadoFuncionaComprobaciones de pareja AMP (#1020):
AMP_NON_200,AMP_MISSING_CANONICAL,#1020
#1020 (incidencia en GitHub)AMP_MISSING_RETURN_LINK,AMP_NON_INDEXABLE_CANONICALyAMP_INDEXABLEleen el destino AMP que una página de escritorio declara con<link rel="amphtml">. Solo se juzgan las páginas AMP que capturó el rastreo; un destino no capturado se omite y queda registrado. El rastreo nativo ahora guarda el destino resuelto en la columnaAMP HTML. Las otras diez reglas AMP de SF siguen descartadas.AñadidoFuncionaAñade
HTML_OVER_2MB, un tope absoluto de 2 MB para el documento HTML, separado de#1019
#1019 (incidencia en GitHub)LARGE_HTML, que es relativo a la mediana. La incidencia «HTML Document Over 2MB» de Screaming Frog ahora se asigna a esta comprobación en lugar de a la regla de 200 KB.AñadidoFuncionaAñade el aviso
URL_HAS_PARAMETERSa la auditoría de rastreo: una página HTML interna#1018cuya URL…
Añade el aviso
#1018 (incidencia en GitHub)URL_HAS_PARAMETERSa la auditoría de rastreo: se informa de cualquier página HTML interna cuya URL lleva parámetros de consulta, independientemente de su estado de canonical.URL_HAS_PARAMSconserva su significado más estricto, solo para páginas sin canonical (#1018).CambiadoFuncionaDirectivas de robots (#1017):
noodpynoydirobsoletas en meta robots o#1017X-Robots-Tag…Directivas de robots (#1017): las directivas obsoletas
#1017 (incidencia en GitHub)noodpynoydiren meta robots o enX-Robots-Tagahora generan los avisosNOODPyNOYDIRen la auditoría de SF; antes figuraban como fuera de alcance.none(noindex + nofollow) queda cubierto por pruebas de regresión tanto para la ruta deX-Robots-Tagcomo para la de meta.AñadidoFuncionaNueva comprobación de rastreo
JS_CONSOLE_ERRORS(SF «Pages with JavaScript Errors»):#1015una página cuya consola de renderizado conservada registró errores. Se lee sin conexión desde los archivos auxiliares de consola guardados de un escaneo nativo, sin volver a renderizar; un registro que no se puede leer se indica como omisión, nunca como página limpia. Requiere
#1015 (incidencia en GitHub)rendering.artifacts.console_errors.CambiadoFuncionaLos rastreos ahora informan de cuatro cabeceras HTTP de seguridad ausentes por página#1013
HTML, a partir de la respuesta final guardada:
#1013 (incidencia en GitHub)MISSING_CSP,MISSING_X_CONTENT_TYPE_OPTIONS,MISSING_X_FRAME_OPTIONS(que se da por cumplida con la directivaframe-ancestorsde CSP) yMISSING_REFERRER_POLICY. Las páginas cuyas cabeceras guardadas no se pueden analizar se cuentan como no medidas, no como limpias, y un rastreo sin escaneo guardado omite esas comprobaciones indicando el motivo.AñadidoFuncionaAñade un validador para especificaciones cerradas de acciones de página (
click,#1011scroll,wait_for_selector…Añade un validador para las especificaciones cerradas de acciones de página (
#1011 (incidencia en GitHub)click,scroll,wait_for_selector,wait_ms) con un presupuesto de tiempo estático para los rastreos renderizados. Todavía no está conectado al renderizado, así que el comportamiento del rastreo no cambia (#1011).CambiadoFunciona
log-analyzelee logs de acceso comprimidos con gzip (archivos rotadosaccess.log.N.gz#1009y…
#1009 (incidencia en GitHub)log-analyzelee directamente los logs de acceso comprimidos con gzip (archivos rotadosaccess.log.N.gzy archivos comprimidos renombrados), detectando el formato por su contenido y no por la extensión. Un archivo truncado o dañado se informa como error, sin recuentos parciales.CambiadoFunciona
scan-url-queryincorpora vistas predefinidas (--preset, por ejemplostatus_4xx,#1007
#1007 (incidencia en GitHub)title_missing,title_over_60,h1_missing,noindex_meta) que se combinan con AND con tus filtros, y--export PATHcon--export-format csv|xlsxescribe todas las filas coincidentes en un archivo nuevo. La exportación se niega por encima de--export-max-rows(por defecto, 100 000) y nunca sobrescribe.CambiadoFuncionaLas reglas de elegibilidad de resultados enriquecidos pasan del código Python a…#1001
Las reglas de elegibilidad de resultados enriquecidos pasaron del código Python a
#1001 (incidencia en GitHub)seohead/data/rich_results_rules.json, un archivo de datos versionado que se incluye con el paquete. El campoversionde ese archivo es el valor que se graba comorules_versionen cada veredicto de resultado enriquecido, así que cambiar una regla significa cambiar datos, no código.CambiadoFuncionaLos veredictos de resultados enriquecidos (
check_schemay las comprobaciones de#1001evidencia estructurada guardada) ahora incluyen
#1001 (incidencia en GitHub)rules_version, de modo que cada resultado indica qué conjunto de reglas sin conexión lo produjo.CambiadoFuncionaDocumenta los seis scripts de mantenimiento y generación que no tenían referencia en la#997
documentación…
Documenta en
#997 (incidencia en GitHub)docs/README.mdlos seis scripts de mantenimiento y generación que no tenían referencia en la documentación (scripts/generate_project_catalogue.py,generate_registry_inventory.py,render_readme_visuals.py,linux_lifecycle_smoke.py,capacity_watchdog.py,profile_million_audit.py): qué escribe cada uno y cuáles se ejecutan en CI (#997).AñadidoFuncionaAñade la canalización del núcleo semántico como
seohead/semantics, con base SQLite#995propia por proyecto…
Añade la canalización del núcleo semántico como
#995 (incidencia en GitHub)seohead/semantics, con su propia base SQLite por proyecto:seohead semantics <stage> --project DIR(init, import, collect, clean, graph, exact, cluster, competitors, synonyms, report, excel, mine, sitematch, relevance, status, export), las herramientas MCPseo_semantics_status,seo_semantics_run,seo_semantics_mineyseo_semantics_paid(las etapas de pago necesitanconfirm_paid=true), la agrupación Louvain tras el nuevo extrasemantics, la skillsemantic-coreempaquetada y un proyecto de ejemplo sintético. Los cargos del proveedor de una etapa semántica se etiquetan en el diario de gasto compartido (#995).CambiadoFuncionaElimina el adaptador guiado de bot de Telegram
seohead/integrations/bot; los recibos de#995entrega del monitor ahora viven en
#995 (incidencia en GitHub)seohead/projects/service_delivery.py(#995).CambiadoFunciona
scan-url-querydevuelveclick_depth, la ruta interna más corta desde la página de#992inicio…
#992 (incidencia en GitHub)scan-url-querydevuelveclick_depth, la ruta de enlaces internos más corta desde la página de inicio del escaneo, como columna, filtro y clave de orden. Las páginas que ningún enlace guardado alcanza sonNULL(huérfanas).crawl_depthno cambia y sigue siendo la profundidad de la frontera, que es 0 para cada URL sembrada desde el sitemap. Un escaneo que no conservó sus enlaces falla conreason_code: click_depth_unavailableen lugar de informar unNULLfalso. El valor se recalcula en cada consulta a partir de la tablalinks; guardarlo como columna indexada al terminar el escaneo sigue pendiente, porque requiere decidir la versión del esquema (#992).CambiadoFunciona
scan-url-queryy su herramienta MCP aceptan un argumento opcionalfacets(una lista#991de grupos…
#991 (incidencia en GitHub)scan-url-queryy su herramienta MCP aceptan un argumento opcionalfacets(una lista de ids de grupo, oall) que devuelve recuentos por grupo (status_2xx–5xx,title_missing,canonical_missing,directives_noindex/nofollow,with_outlinks) sobre los mismos filtros en una sola pasada. Los grupos que necesitan una proyección (interno o externo, sitemap, título duplicado o longitud, canonical propio o ajeno) todavía no están incluidos.CambiadoFuncionaVinculaciones de fuentes del proyecto, primera entrega (#990):
project-sources-link,#990
#990 (incidencia en GitHub)project-sources-unlinkyproject-sources-list(CLI, másseo_project_sources_link|unlink|listen MCP) registran qué ids de recurso del proveedor usa un proyecto local ensources.json, junto aproject.json. Solo sin conexión: sin descubrimiento, sin llamadas al proveedor y sin credenciales;project.jsonnunca se reescribe.CambiadoFuncionaRastreo nativo: nueva comprobación IMG_BROKEN (#989, primera entrega) informa de destinos…#989
Rastreo nativo: nueva comprobación IMG_BROKEN (#989, primera entrega) informa de los destinos de <img> que respondieron con 4xx/5xx, con la página de origen como evidencia. Lee el grafo de recursos guardado y se omite de forma explícita cuando no se midió ninguna imagen.
#989 (incidencia en GitHub)AñadidoFuncionaSe añade un clasificador puro de soft 404 sobre el cuerpo de página guardado#988
(
#988 (incidencia en GitHub)classify_stored_soft404): texto vacío, una frase de error en una página con poco contenido y una coincidencia de simhash con una plantilla de 404. Todavía no está conectado al rastreo y no emite incidencias; esta es la primera entrega de la incidencia #988.CambiadoFuncionaLos rastreos nativos sondean los destinos de canonical y hreflang que ningún enlace#987
alcanzó…
Los rastreos nativos sondean, tras el rastreo y una vez por destino (5000 como máximo), los destinos de canonical y hreflang que ningún enlace alcanzó. Si un destino responde con 4xx/5xx o redirige, se informa CANONICAL_TARGET_ERROR, CANONICAL_TO_REDIRECT o HREFLANG_BROKEN_TARGET, igual que ya ocurría con los destinos rastreados (#987).
#987 (incidencia en GitHub)CambiadoFuncionaLas incidencias de cadena y bucle de redirección de un rastreo nativo ahora incluyen la#985
ruta…
Las incidencias de cadenas y bucles de redirección de un rastreo nativo ahora incluyen la ruta completa de saltos (
#985 (incidencia en GitHub)details.path), para que una corrección pueda indicar cada salto que hay que sustituir. Ref. #985.CambiadoFuncionaLas incidencias de cadena y bucle de redirección de un rastreo nativo ahora incluyen#985
también…
Las incidencias de cadenas y bucles de redirección de un rastreo nativo ahora incluyen también
#985 (incidencia en GitHub)details.inbound_links(enlaces internos que aún apuntan a la primera URL de la cadena, con su texto ancla, limitado a 20) yinbound_links_count; sin un inventario all_inlinks, el campo esnullcon un motivo. Ref. #985.CambiadoFuncionaLos proyectos pueden registrar un enlace a su núcleo semántico como datos introducidos#984
por el operador (
#984 (incidencia en GitHub)semcore_project,semcore_cluster_count,semcore_landing_mapping). El núcleo semántico sigue en su propia base de datos y no se fusiona con la del proyecto; la detección nunca escribe estos datos, y un dato aportado no puede declarar procedencia de detección. Documentado endocs/PROJECTS.md, en «Linking a semantic core» (parcial, #984).CambiadoFuncionaEscritorio: la pantalla de grafo de enlaces sigue el diseño GraphFilters (lienzo y panel#975
de filtros).
El núcleo todavía no devuelve el grafo de enlaces completo, así que el lienzo muestra un estado de espera claro y los filtros permanecen inactivos hasta que lo haga (#975).
#975 (incidencia en GitHub)CambiadoFuncionaOAuth de GSC:
provider-auth --action cancel(CLI) yseo_provider_authaction=cancel…#964OAuth de GSC:
#964 (incidencia en GitHub)provider-auth --action cancel(CLI) yseo_provider_authconaction=cancel(MCP) cancelan un registro de flujo de consentimiento en el navegador que esté pendiente;statusmuestra el flujo pendiente cuando existe. El registro del flujo no guarda material de concesión y caduca a los diez minutos. Es la primera entrega de #964: todavía no hay inicio ni callback en el navegador, así que la superficie pública no crea ningún flujo y el acceso conectado sigue sin afirmarse nunca.CambiadoFunciona
crawl-site --urls/--urls-file --projectahora registra el rastreo por lista de URL como#962una ejecución del observador (
#962 (incidencia en GitHub)mode=list), de modo que aparece enproject-observeyproject-scanscon su artefacto en la carpetascans/del proyecto. Un recolector que falla se registra comofailed; el progreso y la reanudación de las ejecuciones por lista todavía no están cubiertos (#962).AñadidoFuncionaAñade un esquema estructurado de playbooks:
skill-listyscenario-listdevuelven los#955pasos…
Añade un esquema estructurado de los playbooks:
#955 (incidencia en GitHub)skill-listyscenario-listdevuelven los pasos ordenados de cada playbook, yskill-showyscenario-showañaden sus encabezados y pasos, para que un agente lea la forma del método sin analizar Markdown (#955). Nuevo comando CLIscenario-listy herramienta MCPseo_scenario_list.CambiadoFunciona
scan-content-searchacepta--kind regex(MCPkind="regex") para buscar en#954documentos…
#954 (incidencia en GitHub)scan-content-searchacepta--kind regex(MCPkind="regex") para buscar en los documentos conservados con una expresión regular de Python. Las expresiones no válidas se rechazan antes de empezar la búsqueda; un documento que supera el presupuesto de tiempo de la regex se informa como no disponible, nunca como ausente.CambiadoFuncionaLas llamadas a DataForSEO cuya respuesta se pierde (error de red tras enviar la petición)#949
se registran con
#949 (incidencia en GitHub)cost_unknownycharge_status: unknown, de modo quespend-reportlas muestra como inciertas en lugar de contarlas como una llamada medida de coste cero (#949).AñadidoFuncionaNuevo comando
scan-structured-blocks(CLI) y herramienta MCP#948
#948 (incidencia en GitHub)seo_scan_structured_blocks: para una URL conservada, describe cada bloque JSON-LD (su línea de origen, estadovalid/errors/warnings/parse_error, tipos, una lista plana de propiedades, JSON de origen acotado y errores del grafo de Schema.org). Funciona sin conexión, solo sobre el cuerpo completo de la página conservado; no hace peticiones de red ni cambia artefactos.CambiadoFunciona
crawl-sitesin proyecto que escribe un artefacto de escaneo SQLite ahora comparte su#942límite por host…
#942 (incidencia en GitHub)crawl-sitesin proyecto que escribe un artefacto de escaneo SQLite ahora comparte su límite de peticiones por host con otros rastreos simultáneos del mismo host, mediante una programación privada en la carpeta de estado del usuario (~/.config/seohead/.origin-pacing.sqlite). Antes, los rastreos sin proyecto se ejecutaban sin control de ritmo entre procesos.CambiadoFuncionaPerfiles de crawl-site (#941):
crawl-profile listmuestra los nombres de perfil#941guardados y
#941 (incidencia en GitHub)crawl-profile delete NAMEelimina uno; ambos devuelven JSON y rechazan los nombres desconocidos mostrando la lista de perfiles guardados.CambiadoFuncionaPerfiles de crawl-site (#941):
--save-profile NAME --config FILEguarda una#941configuración de rastreo validada como perfil con nombre (se rechaza si incluye cabeceras de credenciales);
#941 (incidencia en GitHub)--profile NAMErastrea con él, y--setsigue aplicándose encima. Los perfiles se guardan en~/.config/seohead/crawl-profileso en la carpeta indicada porSEOHEAD_CRAWL_PROFILES. Listar y borrar perfiles no forma parte de esta entrega.CambiadoFunciona
compare.v1ahora enumera las páginas rastreadas en un solo lado (url_sets:#938only_in_before…
#938 (incidencia en GitHub)compare.v1ahora enumera las páginas rastreadas solo en un lado (url_sets:only_in_before,only_in_aftery recuentos). Cuando alguno de los dos rastreos es parcial,url_sets.unprovenes true, de modo que la ausencia no se presenta como prueba.CambiadoFuncionaLos saltos de cadena de redirección y canonical registran el estado de cada salto, el#930
siguiente Location…
Los saltos de las cadenas de redirección y de canonical registran el estado de cada salto, la siguiente Location (redirects) y el tiempo de respuesta, de modo que la cadena de una URL se lee desde la evidencia guardada sin otra petición (#930).
#930 (incidencia en GitHub)CambiadoFuncionaLos bucles de redirección en cadenas por URL terminan con un paso marcador (
{"url": ..., "loop": true}#930)…
Los bucles de redirección en las cadenas por URL terminan con un paso marcador (
#930 (incidencia en GitHub){"url": ..., "loop": true}) que no se vuelve a solicitar, de modo que la URL repetida queda visible en la evidencia guardada;final_urlsigue apuntando al último salto obtenido (#930).AñadidoFuncionaExpone en CLI y MCP los pasos de creación e ingesta de escaneos del registro de#926
remediación:
#926 (incidencia en GitHub)remediation-create/seo_remediation_createcrea un registro nuevo y vacío vinculado a un proyecto (producer_builddebe ser un SHA de Git completo de 40 caracteres; las rutas existentes se rechazan), yremediation-ingest/seo_remediation_ingestingiere una auditoría guardada como línea base o histórico sin volver a lanzar un rastreo (la reingesta de la misma revisión es idempotente). La lógica de almacenamiento no cambia; esta es la primera entrega de #926.CambiadoFunciona
crawl_sitey las ejecuciones de escaneo informaneffective_max_requests_per_secondy#925
#925 (incidencia en GitHub)warnings: un aviso cuando la tasa efectiva supera 2 req/s (el umbral es estrictamente mayor que 2). La CLI muestra el mismo aviso en stderr; el JSON de stdout y los valores por defecto no cambian. El control de ritmo no se ha tocado.CambiadoFuncionaRegistro estructurado de eventos del proyecto (
events.jsonl): eventos de solo adición#923con origen, actor y texto acotado, que se leen del más reciente al más antiguo, por páginas, con filtros de origen y de texto. Se exponen como
#923 (incidencia en GitHub)project-event-appendyproject-event-pageen la CLI, y comoseo_project_event_appendyseo_project_event_pageen MCP (issue #923).AñadidoFuncionaAñade el comando
ai-columny la herramienta MCPseo_ai_column, la primera entrega dela columna personalizada con IA (ref. #1012). Sobre páginas de escaneo conservadas y seleccionadas, o sobre elementos normalizados que se aporten, prepara un plan acotado a partir del título, los encabezados y un extracto del texto, con una estimación de tamaño basada en caracteres (sin precio aplicado) y el alcance de consentimiento que el agente que llama debe respetar antes de cualquier transferencia. Los valores por URL que se aportan se validan contra el hash de origen de cada página; los valores ausentes, obsoletos, vacíos o demasiado grandes se informan como tales y nunca se rellenan. Un CSV opcional, a prueba de fórmulas, exporta la columna. SEOHEAD no guarda ninguna clave de proveedor ni hace llamadas a modelos.
CambiadoFuncionaComparte los abridores SQLite de solo lectura y de escritura en
seohead.core.sqlite.Los lectores de almacenamiento, el importador de escaneos, el archivo de GSC, el almacén de fuentes, el almacén de unión de evidencias y las dos clases de comprobaciones ahora abren sus bases de datos mediante un único auxiliar para conexión, row factory y PRAGMAs. Las dos clases de comprobaciones cierran sus conexiones de forma explícita. El comportamiento no cambia; la normalización de rutas y el orden de los PRAGMA se mantienen en cada punto de llamada.
CambiadoFuncionaCorrecciones tras una revisión de comprobaciones, fuentes de datos e importación de
evidencias.
Cambios de comportamiento intencionados en estas rutas: - Las cadenas de redirección de exactamente el límite de saltos (por defecto, 20) ahora se resuelven en lugar de informarse como no resueltas. La comprobación de bucles se ejecuta antes que la de límite, tanto en la resolución de cadenas como en los recorridos de la ruta de saltos. - Las comprobaciones de confianza y de citas de EEAT comparan los hosts de destino con su puerto (
netloc), igual que la lógica de host de los enlaces internos. Los sitios con puertos explícitos pueden cambiar sus resultados. - Las comprobaciones de palabras clave de llms.txt buscan los términos ASCII como palabras completas, con plural opcional, así querapid,ShowcaseyToolbarya no pasan. Las raíces cirílicas siguen coincidiendo como subcadenas. - La captura de navegación asigna el motivoreloadarefresh_navigation. Los motivos solicitados sin asignar, comopageBlockInterstitial, se registran como observaciones de frame que el validador acepta. - La detección de tecnologías trata una implicación negada (["not", X]) como si no implicara nada. - La importación de evidencias rechaza los nombres de métrica declarados duplicados, y el descubrimiento en Search Console usa las filas que recibe. - Los reintentos de Yandex Cloud solo esperan entre intentos. Los reintentos de analítica de consultas de Yandex Webmaster esperan antes del siguiente intento. - La construcción del schema pasa sutimeoutal cliente HTTP (por defecto, sin cambios). - El almacén de recibos de entrega se crea con modo 0600 antes de que SQLite lo abra. - Las ejecuciones del grafo semántico se serializan, porque el conjunto de stop words es estado del módulo. El ejecutor semántico informa de los errores de SQLite comook: falseen lugar de lanzar excepciones. - El analizador de errores de CrUX tolera cuerpos de respuesta que no son objetos. - Se eliminó una guardasqlite3 is Noneinalcanzable en el registro.CambiadoFuncionaEscritorio: una pantalla de Backlinks con el diseño v2.
Muestra un estado de espera claro hasta que el núcleo guarde un perfil de enlaces del proyecto (#999); sin filas de ejemplo, y los filtros de grupo están desactivados con el mismo motivo.
CambiadoFuncionaPantalla Crawler de escritorio: añade el banner de resultados temporales con la dirección
seleccionada y el texto de estado (solo se muestra cuando un rastreo sin proyecto devuelve resultados), mueve las acciones de limpiar y guardar como proyecto a un menú de desbordamiento por debajo de 1000 px, mantiene usables el campo de dirección y la tira de pestañas de comprobación en anchos estrechos, desplaza la cabecera de resultados en lugar de comprimir sus columnas, y da a la barra de estado de la aplicación el mismo relleno derecho de 8 px en los temas oscuro y claro.
CambiadoFuncionaEscritorio: pantalla de estados fatales por lienzo ErrorsCore: falta el núcleo, poco
espacio…
Escritorio: pantalla de estados fatales por lienzo ErrorsCore: el núcleo ausente, el poco espacio en disco y la falta de acceso de escritura se muestran a partir de hechos reales; la versión del núcleo y la integridad del escaneo muestran la píldora neutral «unavailable in this core version» hasta que el núcleo las informe.
CambiadoFuncionaEscritorio: el menú de fila de URL y el de cabecera de columna, los grupos de la barra de
menús Edit, Scan y Window, y los menús contextuales de incidencias y tareas siguen el tablero Menus del lienzo. Las entradas que el núcleo todavía no ofrece permanecen visibles y desactivadas, con el motivo en el tooltip.
CambiadoFuncionaEscritorio: la pantalla «Export and reports» sigue el lienzo de diseño ProjExport
(conjunto de datos…
Escritorio: la pantalla «Export and reports» sigue el lienzo de diseño ProjExport (elección de conjunto de datos y de formato, tarjeta de carpeta, exportaciones recientes). Los conjuntos de datos y formatos que el núcleo todavía no puede exportar (comparación, tareas, PDF) se muestran como no disponibles; el botón de ejecutar permanece desactivado hasta que se conecte la exportación (#1191).
CambiadoFuncionaNeutraliza TAB y CR iniciales en los identificadores del inventario de marketing y en los
CSV de revisión de borradores de meta descripción, con el mismo prefijo de apóstrofo que ya se aplica a
=,+,-y@. Ambas protecciones comparten ahoraseohead.core.tabular.neutralize_formula.CambiadoFuncionaPeticiones a proveedores con credenciales (Arsenkin, Metrika, Yandex Cloud, IndexNow…
Las peticiones a proveedores que llevan credenciales (Arsenkin, Metrika, Yandex Cloud, IndexNow, Topvisor y destinos de BI) ya no siguen redirecciones HTTP, así que la cabecera Authorization nunca se vuelve a enviar a otro host. Ahora, una redirección aparece como error HTTP del proveedor.
AñadidoFuncionaAñade el formato de redirecciones
csv(filassource,target,301, entre comillas sihace falta) a
generate_ruley a la ayuda de la CLI deredirects-generate. El formatowordpress-redirectionno se incluye, porque su sintaxis de importación aún no está verificada (#998).CambiadoFuncionaEl diario de ejecuciones (
runs.jsonl) ahora rota al superar un límite de tamaño (5 MiBpor defecto;
SEOHEAD_RUN_LOG_MAX_BYTESlo cambia). La generación anterior se guarda comoruns.jsonl.1, y las lecturas cubren ambos archivos, así que las búsquedas de reutilización siguen viendo las llamadas recientes.CambiadoFuncionaDistribuye la pestaña Schema de la tarjeta de URL del escritorio según la estructura de
lienzo de design-v2 (lista de bloques, árbol de bloques, comprobaciones). El núcleo solo devuelve recuentos de bloques JSON-LD por URL, así que las columnas muestran estados de espera honestos vinculados a la incidencia 948 del núcleo, y los recuentos conocidos siguen siendo reales; no se muestran bloques de ejemplo.
9 de octubre de 2026
4 añadido4 cambiadoAñadidoFuncionaAñade etiquetas de terminal en RU/EN según el idioma, un bloque de progreso del escaneo#951
actual, selección explícita de escaneo y una salida compacta del observador.
#951 (incidencia en GitHub)CambiadoFuncionaLos escaneos guardados se abren ligeramente para lectura (#931).#931
#931 (incidencia en GitHub)scan-status,scan-url-detail,scan-link-inspecty el observador de proyecto (project-scans,project-observe) ya no validan todo el artefacto en cada apertura: comprueban identidad, esquema, versión y la fila de cabecera, toman los contadores de SQL (GROUP BYsobrepages_status) y lo indican en un campovalidationaditivo ("light"o"full"). La validación completa se ejecuta cuando la pides (full_validation: trueenscan-status, o--input '{"input_path": "...", "full_validation": true}'en la CLI) o cuando los mismos bytes (ruta, tamaño, mtime, estado de WAL, hash de cabecera) ya se validaron por completo en el proceso. Un escaneo que no supera las comprobaciones ligeras se rechaza con el mismo error de antes, y cada vía que escribe o registra evidencias sigue validando por completo.scan-url-detailejecuta la búsqueda del destino de redirección (sin índice enresponses.effective_url_id) con un presupuesto de 0,5 s y marcaresponses.redirect_target_lookupcomoskippeden lugar de recorrer una tabla grande.AñadidoFuncionaAñade estado MCP compartido y auditado, con revocación al arrancar y en vivo de llamadas#929
a herramientas; expone la presencia segura de los clientes mediante la CLI.
#929 (incidencia en GitHub)AñadidoFuncionaAñade registro de clientes con permiso explícito, previsualizaciones, escrituras#929
atómicas, copias de seguridad verificadas y restauración segura frente a conflictos.
#929 (incidencia en GitHub)AñadidoFuncionaAñadido
scan-url-query(MCPseo_scan_url_query): lectura filtrada y paginada de solo#927lectura…
Añadido
#927 (incidencia en GitHub)scan-url-query(MCPseo_scan_url_query): lectura de solo lectura, filtrada, ordenada y paginada en el servidor, de toda la tabla de páginas de un escaneo guardado. Devuelvetotal,filtered_total(nullmásfiltered_total_state: cappedcuando el recuento supera su presupuesto de tiempo), una proyección de columnas, etiquetas de cobertura del escaneo, el formatoseohead.scan-url-query.v1y unreason_codelegible por máquina en cada error. Como máximo 200 filas por llamada; ordenar porurl,status_code,page_ordinalourl_idusa índices, y cualquier otra columna necesita un filtro que deje como máximo 100 000 filas (si no,sort_not_indexed). El escaneo se abre con una comprobación ligera de identidad y de generación de esquema, no con validación completa, y nunca se modifica.CambiadoFunciona
scan-link-inspect --view links(MCPseo_scan_link_inspect) pagina los enlaces#924salientes o entrantes de una URL, buscada por dirección y no por ID de documento: ancla,
#924 (incidencia en GitHub)relcon las marcas nofollow/sponsored/ugc, interno o externo, posición guardada, atributotargety el código HTTP del otro extremo (nullcuando esa página no se escaneó). Filtra por tipo de enlace, seguimiento, clase de estado y subcadena;offset/limithasta 200;total/filtered_totalson exactos o están marcados como capped. El escaneo se abre en solo lectura sin validación completa, y los fallos incluyen unreason_codelegible por máquina (url_not_found,scan_not_available,url_not_scanned,links_not_retained). Las vistas y los campos existentes no cambian.CambiadoFuncionaReorganiza el diseño de paquetes, sin capas de compatibilidad:
seohead.serverspasa aser
seohead.mcp,seohead.toolspasa a serseohead.checks,seohead.botyseohead.remote_apise mueven bajoseohead.integrations, la CLI vive en el paqueteseohead.cli(conseohead.cli.terminal_progress), los módulos raíz compartidos (models,graph,filesystem,runlog,verification,canonical_policy,input_contracts,job_contracts,provider_matrix) pasan aseohead.core, y la procedencia de la compilación pasa aseohead._build.provenance.examples/yconfig.example.jsonse mueven adocs/examples/;PROVENANCE.mdyTRADEMARKS.mdse mueven adocs/legal/. Los comandosseoheadysf-analyzerno cambian; las importaciones de Python con las rutas antiguas deben actualizarse.CambiadoFuncionaReescribe el README en torno a la instalación, tres rutas de inicio rápido (del rastreo
nativo al informe, exportaciones sin conexión de Screaming Frog, proyecto más agente), un mapa de funciones por área, un resumen de la CLI, la configuración de MCP para Claude Code y Claude Desktop, la app de escritorio complementaria y el límite entre lo medido y lo no medido, con capturas reales de terminal en
docs/assets/tomadas de un fixture de QA local y del fixture de exportación sintético. Añadedocs/CLI.md, que agrupa cada comando registrado por tarea con sus anotaciones de red, escritura y pago (una prueba de desfase ahora falla si falta un comando), ydocs/WORKFLOWS.md, que documenta los comandos de workflow-run, bandeja de entrada y registros de monitor, que antes solo se mencionaban como referencia.
8 de octubre de 2026
1 añadido10 cambiado1 corregidoCorregidoFuncionaMantiene el cómputo de bytes de HTML/DOM retenido dentro de la transacción e incremental,#914
en…
Mantiene el cómputo de bytes de HTML/DOM retenido dentro de la transacción y de forma incremental, en lugar de volver a recorrer todos los cuerpos guardados por cada respuesta única. Los escritores reabiertos reconstruyen el contador una sola vez; la deduplicación, el rollback, los savepoints y los límites de retención de cuerpos siguen intactos.
#914 (incidencia en GitHub)CambiadoFuncionaLos informes de BI mantienen como desconocidos los estados de recopilación de proveedores#833
no verificados y las marcas de calidad en métricas, cobertura y manifiestos; el muestreo, el umbral o el truncado confirmados se marcan como parciales. Las cohortes búsqueda frente a sesiones exigen calidad de recopilación explícita, medidas de recuento no negativas y ámbitos de fuente cualificados, y conservan la identidad de fuente de cada eje, la atribución, el ámbito de búsqueda y la política de calendario. El paquete sintético de informes sigue funcionando sin conexión; la aceptación nativa en Sheets y Looker sigue siendo un trabajo aparte.
#833 (incidencia en GitHub)CambiadoFuncionaLos escaneos de sitio SQLite nativos aceptan
max_urls=0para recopilar hasta vaciar la#818cola, y
#818 (incidencia en GitHub)max_depth=-1para desactivar el límite de profundidad. Los presupuestos de tiempo y HTTP siguen siendo configurables por separado, las protecciones de almacenamiento y la interrupción con reanudación siguen activas, y las rutas materializadas heredadas rechazan una población de URL sin límite.CambiadoFuncionaLos escaneos solo de sitemap también conservan el límite de URL desactivado, en lugar de#818
rechazar su primer miembro declarado cuando el límite configurado es cero.
#818 (incidencia en GitHub)CambiadoFuncionaLas tasas de petición finitas explícitas por encima de las 2 peticiones/s predeterminadas#818
ahora llegan también al carril compartido de ritmo por origen del proyecto, además del limitador por escaneo. Los escaneos en paralelo reservan una única programación común por host, en lugar de multiplicar su tasa.
#818 (incidencia en GitHub)CambiadoFuncionaInterrumpir el análisis nativo devuelve ahora un resultado interrumpido, explícito y#754
reanudable, y conserva las páginas capturadas en lugar de mostrar un traceback de KeyboardInterrupt.
#754 (incidencia en GitHub)CambiadoFuncionaRegenera el catálogo de proyectos empaquetado tras la actualización del escenario del#754
proveedor Bing.
#754 (incidencia en GitHub)CambiadoFuncionaRechaza las filas de respuesta mal formadas de Bing Webmaster en lugar de informar un#753
resultado vacío completo. Conserva los datos de respuesta sin procesar, las filas de origen y los recuentos exactos devueltos en la evidencia guardada del proveedor. Las respuestas de recuento de enlaces mantienen su envoltorio de página documentado e informan de las poblaciones de varias páginas como parciales cuando solo se recopiló una de las páginas solicitadas.
#753 (incidencia en GitHub)CambiadoFuncionaReconoce el fallback compartido y ya existente de cuenta de servicio de Google en la#753
preparación y el descubrimiento de credenciales del proveedor GA4. Los permisos de cuenta y el acceso al destino siguen sin verificar, las credenciales mal formadas se informan de forma explícita, y se mantiene el soporte de bearer OAuth sin exigir ambas fuentes.
#753 (incidencia en GitHub)CambiadoFuncionaVincula las referencias de capacidades headless con el aislamiento de ejecución nativo y#743
el límite público de enrutamiento del rastreo externo, distinguiendo la implementación interna de la disponibilidad en CLI/MCP, sin cambiar el comportamiento del rastreo ni las afirmaciones de capacidad.
#743 (incidencia en GitHub)AñadidoFuncionaAñade paginación acotada de ejecuciones terminadas a
project-observeen CLI y MCP, sinocultar…
Añade paginación acotada de ejecuciones terminadas a
project-observeen CLI y MCP, manteniendo visible cada registro en ejecución almacenado. Las páginas conservan los ID de ejecución exactos y el orden inverso de admisión; los recuentos y los metadatos de retención describen el almacén actual de 100 registros, no el historial completo. La lectura nunca cambia los estados de ejecución guardados. Las entradas JSON de la CLI conservan su paginación y su ámbito de proyecto, salvo que un flag con nombre explícito los sobrescriba.CambiadoFuncionaGestiona Ctrl+C en todo el traspaso nativo posterior a la recopilación, incluida la
apertura del escaneo guardado, las fases opcionales de seguimiento, el análisis y la finalización. Las capturas sin terminar conservan sus datos y su punto de control reanudable, y devuelven un resultado JSON interrumpido y explícito. Una interrupción tras el commit final conserva el artefacto completado e informa de su disponibilidad real de auditoría. La reanudación explícita completa el trabajo pendiente posterior a la recopilación aunque la cola de URL esté vacía, conservando los flags existentes de omisión de evidencias y los insumos de sitemap retenidos.
7 de octubre de 2026
4 añadido4 cambiado1 corregidoAñadidoFuncionaAñade un fixture desechable de aceptación en Linux para la ejecución real de workers SSH#754
con clave, las descargas de API y TLS autenticadas y el ENOSPC del worker nativo en un tmpfs acotado solo para trabajos. Conserva la cola y la evidencia, y exige un resultado explícito de no éxito, sin reintentos, antes de un nuevo trabajo de recuperación JS. Aclara la diferencia entre las mediciones locales del ciclo de vida y la evidencia de SSH y de contención del sistema operativo.
#754 (incidencia en GitHub)CambiadoFuncionaConserva la evidencia parcial de JavaScript en los resultados de trabajos remotos,#754
incluida la corrección de solo lectura de trabajos antiguos terminados, sin cambiar los artefactos guardados ni los presupuestos de renderizado. Verifica la copia de seguridad y restauración reales de la cola mediante estado autenticado, descargas e idempotencia persistente; mantiene el fixture de recuperación de dos páginas con renderizado completo dentro de sus presupuestos finitos existentes.
#754 (incidencia en GitHub)CambiadoFuncionaDevuelve el código de salida 130 sin traceback cuando SIGINT interrumpe la salida JSON
final tras…
Devuelve el código de salida 130 sin traceback cuando SIGINT interrumpe la salida JSON final después de que un manejador haya terminado. Los artefactos guardados no cambian; un flujo de salida truncado nunca se informa como exitoso.
AñadidoFuncionaRegistra la estrategia de área de contenido usada para generar los hashes y recuentos de
tokens guardados, en lugar de la estrategia de área por defecto del parser. Los selectores explícitos y las exclusiones tienen ahora una procedencia de extracción coincidente, incluso cuando el parser de la página usó su región por defecto.
CorregidoFuncionaMantiene los archivos de preparación SQLite nativos no publicados fuera del historial de
escaneos y de los candidatos de retención; sigue informando de los archivos publicados no válidos y permite los escaneos ocultos normales que nombra el usuario.
AñadidoFuncionaAñadida la recopilación SQLite nativa solo de sitemap: un sitemap explícito define la
población completa de URL solicitada, sin respaldo en la página de inicio, sin expansión de hipervínculos ni expansión de destinos de redirección. Las poblaciones de sitemap vacías, incompletas o que superan el presupuesto se detienen de forma explícita, y la reanudación reutiliza la población retenida sin volver a descargar el XML.
CambiadoFuncionaConserva registros de ejecución de proyecto distintos para capturas nativas simultáneas y
comparte…
Conserva registros de ejecución de proyecto distintos para las capturas nativas simultáneas y comparte, dentro del proyecto, una puerta de envío de 2 peticiones/s para el mismo host público; expone a los observadores el tipo de origen de cada ejecución, su procedencia, la huella de configuración y el límite de tasa agregado.
AñadidoFuncionaAñade búsqueda literal sin conexión sobre HEAD, HTML, texto del cuerpo y marcado
seleccionado por CSS guardados, con cobertura estática o renderizada explícita, cuerpos ausentes desconocidos, fragmentos opcionales redactados y paginación con verificación de integridad para los nuevos paquetes de resultados locales.
CambiadoFuncionaConserva la configuración propia de un rastreo guardado de Screaming Frog al exportarlo:
load-crawl ya no inyecta la configuración actual del spider. Los rastreos en vivo de spider y de lista siguen recibiendo sus perfiles explícitos por ejecución.
6 de octubre de 2026
9 añadido14 cambiado9 corregidoCambiadoFuncionaHace que las pruebas de captura externa propias resuelvan de forma coherente sus hosts#896
virtuales de loopback en todos los sistemas operativos, sin cambiar la política de red de producción.
#896 (incidencia en GitHub)CorregidoFuncionaMantiene la entrada de terminal funcionando por encima del límite de descriptores de#896
select, e impide que Delete o las secuencias de control no compatibles cancelen notas sin guardar.
#896 (incidencia en GitHub)CambiadoFuncionaConserva eventos de navegación del navegador con versión y omisiones acotadas, estado de#826
la captura, política del renderizador y procedencia de URL. Distingue las redirecciones HTTP observadas, la navegación por script, historial o fragmento de Chromium y las causas desconocidas, sin afirmar clics humanos.
#826 (incidencia en GitHub)AñadidoFuncionaExpone la misma evidencia mediante render-check y los informes acotados y sin conexión de#826
scan-navigation; conserva las observaciones parciales cuando el renderizado falla.
#826 (incidencia en GitHub)CambiadoFuncionaMantiene la compatibilidad con rollback conservando la evidencia de navegación dentro de#826
los ajustes extensibles del renderizador; valida la codificación de la prerelease anterior sin debilitar las comprobaciones de procedencia ni tratar los eventos observados como política del renderizador.
#826 (incidencia en GitHub)CorregidoFuncionaMantiene las poblaciones de resumen anidadas grandes, incluidos los histogramas de#818
profundidad, en los complementos PDF completos, sin cargarlas al presupuesto acotado de metadatos de visualización. Conserva los destinos con nombre, los esquemas y los enlaces internos al reescribir los enlaces portátiles del complemento, clonando el documento PDF completo.
#818 (incidencia en GitHub)AñadidoFuncionaAñade
pdf_policy="overview-v1"explícito para las solicitudes PDF de audit.v2 retenidas.#818La primera página distingue el origen completo, los recuentos mostrados y los omitidos; los prefijos de visualización deterministas conservan los estados y motivos de cobertura completos y enlazan con el JSON de auditoría completo en streaming y con los complementos CSV de hallazgos, páginas y ámbito. Un manifiesto de hashes y recuentos registra la procedencia y los límites de recursos. Los destinos existentes se rechazan, las exportaciones se preparan por etapas, y el marcador de finalización del PDF se publica solo cuando todos los complementos obligatorios se validan. El comportamiento por defecto del PDF no cambia: el resumen nunca se selecciona en silencio ni se describe como un PDF exhaustivo. Consulta
#818 (incidencia en GitHub)docs/PDF_OVERVIEW.mdpara ver los límites exactos y la semántica ante fallos.AñadidoFuncionaAñade la operación de solo lectura
page_viewsdel proveedor GA4 para recuentos de#782vistas por fecha, nombre de host y ruta visitada, de forma independiente de las sesiones de páginas de entrada. Reutiliza las credenciales, el transporte y el lector de informes paginados existentes de GA4, con reintentos acotados, resultados de cuota y permisos, metadatos explícitos de zona horaria, muestreo y umbral, y vinculación de URL con el origen declarado. La evidencia restringida del proveedor guardada se normaliza mediante la unión y el pipeline de BI existentes; el tráfico ausente sigue siendo no disponible en lugar de convertirse en cero.
#782 (incidencia en GitHub)CorregidoFuncionaMantiene acotadas las actualizaciones del observador reutilizando la cobertura por sitio#777
y proyectando…
Mantiene acotadas las actualizaciones del observador reutilizando la cobertura por sitio, proyectando la actividad de los colectores en vivo por separado y paginando los hallazgos de audit.v2 sin materializar colecciones del grafo no relacionadas.
#777 (incidencia en GitHub)CambiadoFuncionaConserva cada colector activo en un historial acotado y publica ventanas de contadores#777
medidos…
Conserva cada colector activo en un historial acotado, publica ventanas de contadores medidos con marca de tiempo y distingue los contadores no medidos de cero. Transmite el progreso verificado de Screaming Frog acotando ambos canales de diagnóstico.
#777 (incidencia en GitHub)AñadidoFuncionaAñade páginas de solo lectura para la lista de comprobaciones, el detalle de tareas y los#777
escaneos retenidos, además de un ámbito explícito de métodos aplicables y una proyección de la bandeja de entrada más reciente.
#777 (incidencia en GitHub)CorregidoFuncionaMantiene diferenciadas las ejecuciones de sitemap asociadas explícitamente: los#777
contadores en curso siguen desconocidos, y las mediciones finales cuentan por separado los documentos de sitemap analizados frente a las URL declaradas, los errores y los truncados.
#777 (incidencia en GitHub)CambiadoFuncionaObserva los recibos de artefactos de la lista de comprobaciones mediante metadatos de#777
identidad de…
Observa los recibos de artefactos de la lista de comprobaciones mediante metadatos protegidos de identidad de archivo, sin recalcular el hash de los bytes guardados al actualizar. Las lecturas explícitas de cobertura mantienen la verificación byte a byte; la evidencia cambiada o heredada y no verificada sigue visible como obsoleta o no verificada.
#777 (incidencia en GitHub)CorregidoFuncionaMantiene los recibos históricos de prioridad vinculados a su ámbito original de elementos#777
cuando se añaden tareas tras la preparación, y valida cada candidato de cobertura completo antes de la publicación atómica. Las lecturas de detalle de competidores con ámbito conservan la verificación pasiva de solo metadatos.
#777 (incidencia en GitHub)AñadidoFuncionaAñade comparación explícita de auditorías guardadas en disco, con resultados NDJSON#762
completos, orden determinista, identidades de origen, sumas de comprobación por archivo y conservación de hallazgos antes y después. Las comparaciones grandes de audit.v2 requieren un nuevo directorio de salida; las identidades duplicadas y las colisiones en la correspondencia de URL fallan en lugar de perder filas.
#762 (incidencia en GitHub)CorregidoFuncionaMantiene acotada la verificación dirigida de audit.v2 cuando hay filas duplicadas,#762
conserva la identidad de escaneo validada en los documentos seleccionados y rechaza las identidades en conflicto o los rastreos posteriores no válidos como prueba de corrección.
#762 (incidencia en GitHub)AñadidoFuncionaAñade compresión gzip en streaming opcional para los archivos NDJSON completos de#762
compare.v2, con bytes comprimidos deterministas y hashes exactos de los comprimidos con recuentos decodificados de filas y bytes. Añade un lector acotado que valida exportaciones planas o gzip y rechaza los flujos dañados o los recuentos de manifiesto que no coinciden; la salida plana sigue siendo el valor por defecto.
#762 (incidencia en GitHub)CorregidoFuncionaMantiene la compatibilidad de comparación de corpus guardados como desconocida si falta#762
cualquiera…
Mantiene la compatibilidad de comparación de corpus guardados como desconocida cuando falta alguno de los dos indicadores de completitud, y advierte explícitamente de los corpus parciales conocidos. Conserva los ID y motivos de las comprobaciones omitidas y desactivadas junto con las diferencias de hallazgos, para que las mediciones ausentes no puedan presentarse como corrección verificada.
#762 (incidencia en GitHub)CambiadoFuncionaHace que el observador de proyecto de terminal permita explorar detalles legibles de#752
tareas, métodos, datos estructurados, escaneos, ejecuciones, bandeja de entrada y evidencia guardada, con páginas acotadas y cobertura de ámbito honesta. Las lecturas de almacenamiento y los envíos explícitos de notas se mantienen fuera del bucle de entrada.
#752 (incidencia en GitHub)CambiadoFuncionaConserva borradores de notas y de objetivos por separado durante una sesión, admite#752
edición con cursor, conserva los pegados grandes sin truncar, muestra los recibos de guardado en todos los diseños e imprime los borradores no guardados al salir normalmente de la terminal para poder recuperarlos.
#752 (incidencia en GitHub)AñadidoFuncionaAñade exploración explícita de cobertura y artefactos del sitio propio y de competidores…#752
Añade exploración explícita de cobertura y artefactos del sitio propio y de los competidores, conserva el sitio seleccionado al pasar por las páginas de escaneo y hallazgos, muestra sugerencias recientes de competidores basadas en notas, y mantiene visible el progreso de recopilación medido en terminales compactas. Las muestras obsoletas ya no se animan como progreso en vivo.
#752 (incidencia en GitHub)AñadidoFuncionaAñade un inventario versionado de capacidades headless generado a partir de la#743
configuración real del rastreador, con referencias a implementación, CLI/MCP, pruebas y brechas de aceptación explícitas.
#743 (incidencia en GitHub)AñadidoFuncionaAñade un benchmark opcional de HTML/JavaScript en un origen propio, con fases congeladas,#743
memoria del árbol de procesos, presupuestos de disco y de recuperación. Los navegadores reales crean los DOM medidos; el perfil no establece por sí mismo la capacidad de JavaScript para sitios grandes.
#743 (incidencia en GitHub)CorregidoFuncionaCorrige el argumento de streaming no soportado del puente JavaScript nativo y conserva#743
los contadores de renderizado ya observados durante la cancelación controlada y la reanudación.
#743 (incidencia en GitHub)CambiadoFuncionaPermite que log-scan consuma rutas de escaneo nativas guardadas y complementos audit.v2#711
sin materializar JSON heredado. Procesa en streaming los hallazgos de consistencia, mantiene en disco la pertenencia a páginas nativas y la deduplicación de hallazgos, conserva los recuentos exactos de anomalías y limita solo los ejemplos. Informa explícitamente de que falta la traza nativa de decisiones de exclusión.
#711 (incidencia en GitHub)CambiadoFuncionaReconoce un hallazgo de lastmod de sitemap de todo el sitio en el origen raíz de su sitio#711
medido cuando no se rastreó la página de inicio. La excepción requiere evidencia de resumen de sitemap coincidente y no exime los hallazgos de página, los hosts no relacionados ni las rutas de destino no compatibles.
#711 (incidencia en GitHub)CambiadoFuncionaCompara escaneos audit.v2 guardados mediante una clave exacta y un índice ordinal, sin
duplicar las cargas de páginas y hallazgos en el almacenamiento SQLite temporal. Las filas completas, las exportaciones deterministas planas o gzip, las identidades de origen y las entradas heredadas siguen siendo compatibles. Los lectores de auditoría fijan la instantánea validada mediante lecturas indexadas de filas.
CambiadoFuncionaRevertir los miembros de salida de comparación propios ante un fallo tardío de
publicación y rechazar destinos añadidos en paralelo…
Revierte los miembros de salida de comparación propios si la publicación falla tarde y rechaza los destinos añadidos en paralelo; el manifiesto sigue siendo la marca final de confirmación del paquete.
CambiadoFuncionaHacer que la entrada pública describa la ingeniería SEO configurable con agentes y enlace
toda la superficie de capacidades a sus métodos, entradas y límites de evidencia. Corregir la guía obsoleta sobre nativo/SF, cobertura de proyectos y remediación; documentar por separado el libro de trabajo para desarrolladores redactado por el agente frente a la salida factual del informe, incluidos los criterios de aceptación revisados y los enlaces a las fuentes.
CorregidoFuncionaRestaurar la paridad de los informes para personas entre las entradas audit.v2
transmitidas y el JSON de auditoría equivalente.
Markdown ahora comparte un único renderizador incremental, que incluye las explicaciones de comprobaciones no disponibles, los registros de exclusión y las notas finales de cobertura. XLSX comparte un mismo diseño de metadatos y escribe las incidencias y las páginas con hojas de solo escritura de tamaño acotado, conservando todas las hojas, columnas, filtros, gráficos y recuentos de origen. Las incidencias suprimidas retenidas se pueden reproducir sin materializar su colección, y las URL de ejecución que faltan usan la misma alternativa de primera página.
CambiadoFuncionaEtiquetar la procedencia de las auditorías PDF de forma independiente del esquema de
auditoría compartido: rastreador nativo, exportaciones de Screaming Frog o un recopilador SF identificado explícitamente, y recopilador desconocido. Una auditoría nativa que usa el esquema de SF Analyzer ya no recibe un encabezado de Screaming Frog.
CambiadoFuncionaTransmitir a CSV las filas de alcance de incidencias suprimidas en lugar de acumular sus
explicaciones renderizadas…
Transmitir a CSV las filas de alcance de incidencias suprimidas en lugar de acumular en memoria sus explicaciones renderizadas. Las exportaciones completas de exclusiones conservan su orden y los datos de origen, mientras la asignación de memoria sigue acotada para colecciones grandes de exclusiones retenidas.
5 de octubre de 2026
1 cambiadoCambiadoFuncionaConciliar cada fila de brecha de cobertura a partir de su celda Mode real, validar las#830
referencias a comprobaciones y herramientas cubiertas contra los registros públicos, y generar prioridades a partir de las filas sin resolver.
#830 (incidencia en GitHub)
4 de octubre de 2026
56 añadido75 cambiado5 corregidoAñadidoFuncionaAñadir una proyección sin conexión del avance de GSC de marca y sin marca con alias#880
Unicode explícitos…
Añadir una proyección sin conexión del avance de GSC de marca y sin marca, con alias explícitos compatibles con Unicode, CTR ponderado compatible y bandas de posición media etiquetadas.
#880 (incidencia en GitHub)AñadidoFuncionaAñadir el agrupamiento opcional de tareas
check_assignmentpara las asignaciones de URL#878de plantilla o componente declaradas…
Añadir el agrupamiento opcional de tareas
#878 (incidencia en GitHub)check_assignmentpara asignaciones de URL de plantilla o componente declaradas, o para segmentos de rastreo validados. Los elementos agrupados conservan los recuentos de ocurrencias y de URL, la evidencia limitada, la procedencia del agrupamiento, el alcance de verificación y los estados declarado, candidato, confirmado y sin asignar.AñadidoFuncionaAñadir mapas de comparación de versiones
url-correspondence.v1opcionales con pares#877declarados de origen y URL…
Añadir mapas opcionales de comparación de versiones
#877 (incidencia en GitHub)url-correspondence.v1con pares declarados de origen y URL, rechazo de colisiones, procedencia de los datos de página y salidarelease_review.v1.AñadidoFuncionaAñadir una proyección sin conexión de cohortes de publicación con evidencia cualificada y#876
procedencia de fechas…
Añadir una proyección sin conexión de cohortes de publicación con evidencia cualificada, procedencia de fechas, inventario de autores, observaciones de proveedores etiquetadas y ventanas de antigüedad opcionales.
#876 (incidencia en GitHub)AñadidoFuncionaAñadir un inventario sin conexión de CTA y formularios incrustados que conserve las#875
ocurrencias para el HTML proporcionado…
Añadir un inventario sin conexión de CTA y formularios incrustados que conserve las ocurrencias del HTML proporcionado, con destinos ausentes anulables, salida JSON/CSV acotada y cobertura explícita de cuerpos incompletos.
#875 (incidencia en GitHub)CambiadoFuncionaConservar la clasificación de tiempo de espera remoto al ocultar los datos sensibles de#866
los errores de transporte, y reproducir de forma segura los manifiestos de proxy directo para la verificación dirigida.
#866 (incidencia en GitHub)CambiadoFuncionaLeer la evidencia de atribución desde el grafo de enlaces SQL retenido, conservar la#866
atribución nula explícita en la exportación…
Leer la evidencia de atribución desde el grafo de enlaces SQL retenido, conservar la atribución nula explícita al exportar y mantener las comprobaciones de enlaces externos en cola entre reanudaciones.
#866 (incidencia en GitHub)CambiadoFuncionaRegenerar los catálogos integrados y los contratos de informes; instalar el validador PDF#866
con el extra all y mantener las pruebas con navegador simulado independientes de la selección local de Chrome.
#866 (incidencia en GitHub)AñadidoFuncionaAñadir un plan opcional y sin conexión de carga en BigQuery que exponga tablas#837
versionadas por esquema, requisitos de facturación y prerrequisitos explícitos de autorización, sin acceso a la nube.
#837 (incidencia en GitHub)AñadidoFuncionaAñadir un transporte REST de BigQuery con lista de permitidos y trabajos de carga#837
deterministas en staging…
Añadir un transporte REST de BigQuery con lista de permitidos, trabajos de carga deterministas en staging, conciliación del recuento de filas y publicación atómica documentada por tabla, en lugar de una transacción ficticia entre tablas.
#837 (incidencia en GitHub)CambiadoFuncionaExigir una aprobación
cost_authorizedde BigQuery separada y controlada por el host#837antes de cualquier token, comprobación de conjunto de datos o escritura en staging.
#837 (incidencia en GitHub)AñadidoFuncionaAñadir un generador validado y solo local de enlaces de copia para Looker Studio del#836
paquete de informes sintético de cinco páginas…
Añadir un generador validado y solo local de enlaces de copia para Looker Studio, destinado al paquete de informes sintético de cinco páginas; exige un ID de informe original y alias exactos de origen de Sheets o BigQuery, sin publicar ningún informe ni inventar una plantilla.
#836 (incidencia en GitHub)AñadidoFuncionaAñadir el accesorio sintético de hojas de cálculo confirmado#836
(
#836 (incidencia en GitHub)examples/reporting-pack/worksheets/): un CSV por cada conjunto de datos de BI, más el manifiesto, generado de forma determinista byte a byte a partir deexamples/audit.jsony de dos entradas sintéticas de GSC/GA4. Muestra los estados de cero medido, suprimido o ausente, solo externo, sin clave identificable, comprobación omitida, conjunto de datos no disponible y cuadrante incompleto, y se verifica como reproducible conscripts/generate_reporting_pack_worksheets.py --check.AñadidoFuncionaAñadir
examples/reporting-pack/SETUP.md: la guía mecánica para el propietario sobre#836cómo importar…
Añadir
#836 (incidencia en GitHub)examples/reporting-pack/SETUP.md: la guía mecánica para el propietario que explica cómo importar las seis hojas de cálculo en Google Sheets, conectar los alias reservados de origen de datos, construir las cinco páginas del esquema con los controles declarados y los campos calculados, habilitar el permiso de copia y verificar una copia nueva. La plantilla nativa de Looker Studio sigue siendo un paso externo que debe autorizar el propietario; no se incluyen ID de informe, enlaces ni escrituras en Google.CambiadoFuncionaConservar los nombres de partición, los recuentos y las sumas de comprobación del paquete#836
BI generado para que el accesorio de hoja de cálculo…
Conservar los nombres de partición, los recuentos y las sumas de comprobación del paquete BI generado, para que el accesorio de hoja de cálculo supere la validación previa existente de Sheets y los consumidores de exportaciones filtradas. Documentar los campos de alias separados de la API de enlaces y exigir una verificación de copia nueva a través de la URL generada, sin reparar manualmente el origen.
#836 (incidencia en GitHub)CambiadoFuncionaRechazar alias duplicados de la API de enlaces tras normalizar los espacios y devolver#836
los alias exactos usados en los parámetros de URL. Definir ID compartidos de campos de ejecución, controles de fecha de proveedor agrupados y gráficos de cobertura que excluyan poblaciones solapadas. La creación de la plantilla nativa y la verificación de copia nueva siguen siendo requisitos de aceptación externos.
#836 (incidencia en GitHub)AñadidoFuncionaAñadir filas de cohorte de URL explícitas y con evidencia cualificada a los paquetes BI#835
locales, incluidos los cuadrantes de Search Console/GA4 seguros para el cero medido, solo para observaciones completas, compatibles y uno a uno.
#835 (incidencia en GitHub)CambiadoFuncionaCalcular las cuotas de enlaces entrantes observados a partir de páginas de enlace únicas#835
dentro del alcance con extracción HTML completa…
Calcular las cuotas de enlaces entrantes observados a partir de páginas de enlace únicas dentro del alcance, con extracción HTML completa, conservando por separado las ocurrencias repetidas y etiquetando las poblaciones parciales.
#835 (incidencia en GitHub)AñadidoFuncionaAñadir paquetes BI sin conexión, tipados y deterministas para rastreos y auditorías#834
guardados y para evidencia de proveedores…
Añadir paquetes BI sin conexión, tipados y deterministas para los rastreos y auditorías guardados y para la evidencia de proveedores aportada, con límites de particiones, estados nulos, conservación de filas y celdas CSV seguras frente a fórmulas.
#834 (incidencia en GitHub)CambiadoFuncionaConservar los hallazgos de los archivos complementarios audit.v2 acotados, unir hasta#834
1 000 000 de URL de rastreo retenidas mediante un artefacto SQLite de evidencia duradero y volcar ese artefacto a BI sin materializar listas de páginas ni de URL coincidentes. Esto no entrega una plantilla de Looker Studio que se pueda copiar.
#834 (incidencia en GitHub)CambiadoFuncionaProyectar grupos de hallazgos, candidatos de cuadrantes de proveedores y fuentes de#834
enlaces entrantes elegibles mediante un índice SQLite desechable y acotado. Mantener válidas las dimensiones dinámicas de proveedores en las exportaciones seleccionadas y en los planes sin conexión de Sheets y BigQuery; acotar el número de particiones y el consumo de disco.
#834 (incidencia en GitHub)CambiadoFuncionaConservar las URL de destino y los mensajes de los hallazgos de auditoría nativos como#834
columnas BI tipadas, no solo en el JSON de origen…
Conservar las URL de destino y los mensajes de los hallazgos de auditoría nativos como columnas BI tipadas, no solo dentro del JSON de origen conservado, de modo que las selecciones exactas de URL conserven los hallazgos afectados.
#834 (incidencia en GitHub)AñadidoFuncionaAñadir
scan-fragment-links(seo_scan_fragment_links) y la comprobación de auditoría#827
#827 (incidencia en GitHub)BROKEN_BOOKMARK: cada<a href>con fragmento en el HTML o DOM completo conservado se resuelve contra los ids de elemento y los destinos<a name>del documento de destino, con el algoritmo WHATWG de desplazamiento al fragmento (el fragmento serializado se prueba primero contra ids y nombres; después, el valor decodificado en porcentaje y UTF-8 se prueba contra ambos;+sigue siendo un signo más literal;#y#topse resuelven al inicio del documento). Las representaciones estática, renderizada y de fragmento heredado se evalúan de forma independiente, se respetan las reglas de redirección y de<base href>, y una cadena de consulta distinta corresponde a otro documento. Los cuerpos ausentes, truncados, no compatibles, fallidos o agotados por presupuesto se informan como omisiones con nombre —nunca como incidencias de enlace roto—, y las exportaciones de Screaming Frog y las importaciones heredadas indican que la comprobación no está disponible, en lugar de afirmar que se ejecutó sin errores. Los resultados están acotados y paginados de forma determinista (total,returned,offset/limit,next_offset, estado de cobertura), e idénticos en la CLI, en el MCP y en el resumen de auditoría del rastreo conservado. No se descarga nada: la evaluación es de solo lectura y sin conexión.CambiadoFuncionaValidar los enlaces de retorno de hreflang nativos contra declaraciones completas de#825
destinos conservados, distinguiendo un retorno ausente conocido de un destino no rastreado o con cuerpo no disponible. Informar de las alternativas noindex observadas, conservar las etiquetas sin procesar y las identidades de URL normalizadas con el contexto de duplicados y conflictos, y marcar como no medidas las relaciones de población parcial. La auditoría, la CLI, el MCP y las superficies de informes existentes transportan los mismos hallazgos sin hacer solicitudes adicionales.
#825 (incidencia en GitHub)AñadidoFuncionaAñadir
CANONICAL_TARGET_ERRORpara señalar las URL canonical de destino recuperadas que#824devuelven 4xx/5xx, con evidencia de origen, destino, respuesta e indexabilidad. Los destinos desconocidos o con estado incompleto siguen sin disponibilidad; las variantes 2xx conocidas eliminan el veredicto de error, y los destinos 3xx permanecen bajo
#824 (incidencia en GitHub)CANONICAL_TO_REDIRECT.AñadidoFuncionaAñadir
CANONICAL_HOMEPAGE_GROUPpara grupos de al menos tres páginas recuperadas e#824indexables, repartidas en dos o más secciones de ruta, con títulos y encabezados H1 distintos y con canonical apuntando a la página de inicio recuperada. Las autorreferencias y la página de inicio, las variantes con consulta, la paginación reconocible, los patrones de paginación o filtro configurados, la evidencia incompleta de la página de inicio y los rastreos nativos parciales no generan un hallazgo de todo el sitio.
#824 (incidencia en GitHub)AñadidoFuncionaAñadir evidencia objetiva de autoría, fechas y páginas de confianza a las auditorías#823
acotadas (issue #823): ocho comprobaciones de severidad de aviso en
#823 (incidencia en GitHub)seohead/sf/core/eeat.pyque informan de lo que puede observar un rastreo, y nunca una puntuación E-E-A-T.NO_AUTHOR_BYLINEyNO_CONTENT_DATESsolo se activan en páginas con forma de contenido —un tipo de artículo JSON-LD,og:type=article, un elemento<article>o una ruta de contenido convencional— y nombran los portadores que leen (meta_author,rel_author,itemprop=author, clasebyline,<time datetime>,author,datePublishedydateModifiedde JSON-LD, una ruta de URL con forma de fecha), cada uno con una confianza declarada.MISSING_ABOUT_PAGE,MISSING_CONTACT_PAGE,MISSING_PRIVACY_POLICYyMISSING_TERMS_PAGEinforman uno defound_indexable(silencioso),found_non_indexable,found_error,discovered_not_crawledonot_discovered, de modo que una página que existe pero no responde nunca se lea igual que una que nadie enlazó.FEW_CITATIONSinforma solo de lo que pueden demostrar las posiciones de los enlaces —un enlace saliente dentro del texto del cuerpo o un recuento declarado de cero—, yYMYL_REVIEW_CANDIDATEmarca coincidencias deterministas de palabra completa en la ruta o el título para revisión humana, nunca una clasificación. Lo no medido se mantiene distinto de lo ausente en todo momento: una página cuyo cuerpo nunca se analizó conservatrust_signalsen NULL y se cuenta en el motivo de omisión, ysummary.trust_evidenceregistra el alcance evaluado, el estado por tipo y por página, y una advertencia de rastreo parcial para los veredictosnot_discovered.CambiadoFuncionaClasificar el p75 de LCP, INP y CLS de campo de la ventana actual de CrUX frente a#822
umbrales oficiales versionados, conservando el alcance de URL u origen, factor de forma y periodo de recopilación. Los datos de campo ausentes, incompletos o fallidos siguen como no disponibles o parciales.
#822 (incidencia en GitHub)AñadidoFuncionaAñadir muestreo explícito y acotado de URL con caché privada opcional, y aceptar#822
evidencia guardada de CrUX en las auditorías de sitio y en los informes sin solicitudes automáticas al proveedor. Acotar los bytes de respuesta y de caché, y rechazar recuentos de muestra guardados incoherentes o registros de URL repetidos, en lugar de informar una cobertura de campo completa.
#822 (incidencia en GitHub)CambiadoFuncionaDocumentar el límite actual de la CLI de Docker de un solo uso por separado del servicio#820
opcional de API remota y trabajador…
Documentar el límite actual de la CLI de Docker de un solo uso por separado del servicio opcional de API remota y de trabajador, construido de forma explícita.
#820 (incidencia en GitHub)AñadidoFuncionaAñadir la receta de ejecución SSH con espacio de trabajo persistente y explicar que el#820
estado de salida y de artefactos de la CLI…
Añadir la receta de ejecución SSH con espacio de trabajo persistente y explicar que el código de salida y el estado de los artefactos de la CLI no son una comprobación de salud de un servicio HTTP.
#820 (incidencia en GitHub)CambiadoFuncionaAdmitir configuraciones explícitas de rastreo SQLite nativo de hasta 1 000 000 de URL con#818
un presupuesto separado…
Admitir configuraciones explícitas de rastreo SQLite nativo de hasta 1 000 000 de URL, con un presupuesto separado de 2 000 000 de solicitudes HTTP y el perfil sintético existente de solo almacenamiento. La CLI, el MCP, la cola remota y los trabajadores respetan los mismos presupuestos declarados. Las API materializadas heredadas y de listas conservan un límite de seguridad explícito de 50 000 URL; las comprobaciones de robots, los reintentos y los saltos de redirección y canonical de las listas ahora comparten su presupuesto de solicitudes. Las auditorías nativas y el reanálisis sin conexión usan la ruta acotada audit.v2 sin la antigua negativa del puente, que superaba 10 000 páginas o 20 000 formularios. Los contadores del escritor transaccional evitan volver a recorrer la cola de URL pendientes en cada lote. Un controlador manual de aceptación registra las identidades de origen cargadas, la interrupción y reanudación, y los consumidores posteriores; la admisión, por sí sola, no es evidencia de una aceptación completada de un millón de URL.
#818 (incidencia en GitHub)CambiadoFuncionaEjecutar cada etapa manual de aceptación nativa bajo un vigilante de recursos de#818
subproceso, conservar los artefactos interrumpidos, verificar cada fila CSV o XLSX y la cobertura de tareas, y probar por separado el HTTP protegido en loopback propio, con el ritmo predeterminado sin cambios.
#818 (incidencia en GitHub)CambiadoFuncionaPermitir duraciones de rastreo remoto explícitamente autorizadas de hasta 14 días,#818
conservando la hora predeterminada…
Permitir duraciones de rastreo remoto explícitamente autorizadas de hasta 14 días, conservando el valor predeterminado de una hora y los presupuestos independientes de proyecto, solicitudes, disco, concesión y renderizado. Esto permite que un objetivo de un millón de páginas quepa en su tasa de solicitudes respetuosa sin cambios; los valores por encima del techo de duración y los tipos no válidos fallan antes de la recopilación.
#818 (incidencia en GitHub)CambiadoFuncionaEl reanálisis sin conexión usa un plazo nuevo para cada operación de ejecución o#818
recuperación de SQLite, conservando la interrupción y la cancelación de consultas, sin cargar contra el plazo de validación de apertura del rastreo original el tiempo de análisis en Python ni las escrituras derivadas.
#818 (incidencia en GitHub)CambiadoFuncionaLa opción
crawl-site --out-dirheredada conserva ahora la evidencia de páginas, enlaces#817y formularios en archivos JSONL complementarios…
La opción heredada
#817 (incidencia en GitHub)crawl-site --out-dirconserva ahora la evidencia de páginas, enlaces y formularios en archivos JSONL complementarios de solo anexión durante la recopilación y la reanudación, en lugar de retener listas duplicadas en memoria. Los puntos de control verifican los recuentos de los complementarios; los puntos de control v4 antiguos con formularios en línea migran sin perder hallazgos de formularios. El puente de auditoría existente nombra sus límites de materialización de páginas, formularios y enlaces, y conserva la evidencia recopilada cuando la auditoría no está disponible. Un informe anterior se conserva con un nombre de archivo obsoleto en lugar de presentarse como la ejecución actual. La escalada nativa de JavaScript lee los registros de página a través de una vista SQLite reiterable, en lugar de reconstruir todos los objetos de página. La transmisión completa de auditorías grandes sigue en seguimiento en #816/#817.CambiadoFuncionaAlmacenar auditorías nativas de gran tamaño en archivos complementarios audit.v2#817
ordenados en lugar de descartar la disponibilidad…
Almacenar auditorías nativas de gran tamaño en archivos complementarios audit.v2 ordenados, en lugar de descartar la disponibilidad de la auditoría.
#817 (incidencia en GitHub)CambiadoFuncionaTransmitir la normalización de auditoría nativa a su contexto sin una lista intermedia de#817
registros.
#817 (incidencia en GitHub)CorregidoFuncionaMantener los mapas de páginas de auditoría nativa y las métricas derivadas por página en#817
un almacén de contexto SQLite temporal.
#817 (incidencia en GitHub)CorregidoFuncionaMantener los hallazgos nativos en disco hasta que la agregación ordenada asigne sus#817
identidades de informe.
#817 (incidencia en GitHub)CorregidoFuncionaMantener los grupos nativos de duplicados y contenido en almacenamiento SQLite ordenado#817
durante el análisis.
#817 (incidencia en GitHub)CambiadoFuncionaAcotar las búsquedas repetidas de páginas, agrupar los backlinks de hallazgos y resolver#817
las profundidades de descubrimiento nativo sin reconstruir cada ruta ni cargar cada nodo en Python. Las rutas largas conservan su profundidad exacta y los extremos truncados quedan explícitos.
#817 (incidencia en GitHub)CambiadoFuncionaTransmitir la entrada de página nativa conservada y las búsquedas de enlaces entrantes#817
antes de construir el contexto.
Derivar las relaciones del corpus no vacío y de hreflang mediante índices respaldados en disco, conservar las colecciones completas de evidencia en audit.v2 y etiquetar las muestras acotadas de hallazgos de relación con sus recuentos exactos de ocurrencias.
#817 (incidencia en GitHub)CambiadoFuncionaAcotar la caché de páginas por los bytes decodificados estimados de Python, además del#817
número de entradas; las páginas sin caché…
Acotar la caché de páginas por los bytes decodificados estimados de Python, además del número de entradas; las páginas grandes sin caché siguen siendo legibles y las mutaciones invalidan su peso anterior en caché. Conservar los rangos de tamaño HTML como pares escalares estables de URL y tamaño, en lugar de retener cada modelo completo de página, y evitar retener el JSON serializado de página en los callbacks de mutación.
#817 (incidencia en GitHub)CambiadoFuncionaConservar solo los datos escalares de URL, estado, indexabilidad, canonical y redirección#817
mientras se comprueban los pares con barra final…
Conservar solo los datos escalares de URL, estado, indexabilidad, canonical y redirección mientras se comprueban los pares con y sin barra final, y cerrar explícitamente las conexiones SQLite duraderas del adaptador y de los trabajos remotos.
#817 (incidencia en GitHub)CambiadoFuncionaTransmitir los recuentos de cobertura de cuerpos no disponibles y de charset, conservar#817
el estado escalar de selección de páginas de confianza en lugar de las poblaciones de páginas candidatas, y procesar las coincidencias de DOM en HTML almacenado en dos pasadas sobre el índice de archivos fijo. Conservar el orden del representante de las variantes normalizadas, los ejemplos de URL existentes, la cobertura completa de fuentes coincidentes y cada hallazgo.
#817 (incidencia en GitHub)CambiadoFuncionaValidar fila a fila el JSONL de puntos de control de rastreo heredado antes de añadirlo,#817
rechazando evidencia ausente, corrupta o sin terminar, sin reemplazarla. Comparar los puntos de control de formularios en línea más antiguos con su complementario sin asignar una segunda lista de formularios.
#817 (incidencia en GitHub)AñadidoFuncionaAñadir la continuación de la prueba comparativa de JavaScript con procedencia verificada#817
entre pares completados, conservando los recibos anteriores y los presupuestos de disco. Los casos interrumpidos siguen como bloqueos explícitos. Exigir una consulta o un reanálisis exitosos y evidencia CSV completa de páginas antes de marcar un caso de prueba comparativa como superado.
#817 (incidencia en GitHub)CambiadoFuncionaConservar listas explícitas de URL con el escritor SQLite nativo, preservando el orden#817
exacto de entrada, varios hosts y la semántica de no descubrimiento. Transmitir la entrada de archivos de intercambio, conservar los presupuestos de solicitudes y de tiempo durante la reanudación de la recopilación, retener la evidencia acotada de respuestas y saltos, y mantener las comprobaciones de grafo y de formularios explícitamente no disponibles. Las listas de directorios grandes usan el mismo almacenamiento temporal con un puente de auditoría JSON acotado por separado.
#817 (incidencia en GitHub)AñadidoFuncionaAñadir un archivo complementario SQLite audit.v2 versionado para colecciones de auditoría#816
completas y ordenadas que superen el límite de tamaño de JSON en línea, con vinculación de procedencia del rastreo y validación de integridad de extremo a extremo.
#816 (incidencia en GitHub)CambiadoFuncionaTransmitir informes audit.v2 en JSON, CSV, XLSX, Markdown y DOCX, comparar poblaciones de#816
hallazgos de severidad alta…
Transmitir informes audit.v2 en JSON, CSV, XLSX, Markdown y DOCX, comparar las poblaciones de hallazgos de severidad alta y mantener las operaciones de instantánea y poda emparejadas con el complementario, conservando el esquema scan.v1.
#816 (incidencia en GitHub)CambiadoFuncionaConservar una sola vez la pertenencia a grupos ordenados grandes en la revisión 3 del#816
almacenamiento audit.v2 y la revisión 5 del registro…
Conservar una sola vez la pertenencia a grupos ordenados grandes en la revisión 3 del almacenamiento audit.v2 y en la revisión 5 del registro, con lecturas de auditoría retrocompatibles, migración atómica del registro, paginación explícita de miembros mediante CLI o MCP, y complementarios de pertenencia BI completos y vinculados a su fuente.
#816 (incidencia en GitHub)CambiadoFuncionaConservar el digest de origen audit.v2 durante el reanálisis sin conexión; persistir el#816
alcance incompleto de grupos del registro…
Conservar el digest de origen audit.v2 durante el reanálisis sin conexión; persistir el alcance incompleto de los grupos del registro y cerrar los recursos de ingesta tras una validación fallida.
#816 (incidencia en GitHub)CambiadoFuncionaReutilizar el resumen exacto de capacidades del corpus mientras un rastreo nativo solo de#815
metadatos no tiene evidencia de respuesta, documento, cuerpo ni recurso, evitando relecturas de todo el corpus en cada confirmación de página dispersa, sin cambiar el almacenamiento del rastreo.
#815 (incidencia en GitHub)AñadidoFuncionaAñade un perfilador de capacidad de escaneo nativo, opcional y sin conexión, con enlaces#815
y DOM…
Añade un perfilador de capacidad de escaneo nativo, opcional y sin conexión, con enlaces, HTML conservado y DOM renderizado dimensionados por separado, presupuestos de recursos explícitos y un ejercicio de pérdida de proceso y reanudación. Informa del límite de admisión existente de 50 000 URL y de la finalización incompleta como evidencia bloqueada, no como capacidad.
#815 (incidencia en GitHub)CambiadoFuncionaNombra la cancelación de solicitudes fijadas del navegador como
render_cancelledy#811cierra el contexto aislado…
Nombra la cancelación de solicitudes fijadas del navegador como
#811 (incidencia en GitHub)render_cancelledy cierra el contexto remoto aislado y el navegador al cancelar o al desconectarse, sin recurrir a una alternativa local.CambiadoFuncionaPermite que la configuración remota de proyecto de confianza aporte referencias de#810
credenciales de entorno vinculadas al host, con procedencia conservada y redactada, y falla antes de recopilar datos si una referencia no está disponible.
#810 (incidencia en GitHub)CambiadoFuncionaPermite un transporte remoto de Playwright gestionado por el servicio y con control de#809
versión para un proyecto en cola, manteniendo su endpoint fuera de los envíos y conservando las solicitudes de navegador fijadas y sujetas a política.
#809 (incidencia en GitHub)AñadidoFuncionaExpone las rutas observadas, los enlaces entrantes inversos y el contexto de aparición de#807
un escaneo guardado mediante una única consulta compartida de CLI y MCP, acotada y de solo lectura, con identidad de escaneo explícita y resultados de error.
#807 (incidencia en GitHub)AñadidoFuncionaAñade la ubicación de enlaces por aparición y el contexto del encabezado más cercano,#806
acotados y de solo lectura, a partir del HTML estático conservado y del DOM renderizado. Preserva los ID de enlace duplicados y los estados explícitos de evidencia no disponible o parcial.
#806 (incidencia en GitHub)AñadidoFuncionaNuevo comando
semantic-inputs(seo_semantic_inputspor MCP) que construye el#801manifiesto de entradas…
Nuevo comando
#801 (incidencia en GitHub)semantic-inputs(seo_semantic_inputspor MCP) que construye el manifiesto reproducible de entradas normalizadas que consumirá el trabajo de similitud semántica. Por cada documento registra el hash del cuerpo conservado, el hash exacto de la entrada decodificada, el hash de la salida normalizada, la estrategia de área de contenido y la evidencia de idioma (el propio<html lang>de la página y la proporción de letras por sistema de escritura), pero nunca el texto normalizado en sí.--scanlee en flujo los cuerpos completos conservados, sin conexión y con la configuración de área de contenido registrada en el rastreo, sin volver a descargar nada. Un cuerpo ausente o parcial queda como omisión explícita y nunca como un resultado limpio y vacío (#801).CambiadoFuncionaValida páginas, tamaño, texto extraíble y conservación del modelo de origen del PDF de#800
auditoría técnica…
Valida el número de páginas, el tamaño en bytes, el texto extraíble y la conservación de los registros del modelo de origen del PDF de auditoría técnica antes de publicar un informe renderizado.
#800 (incidencia en GitHub)AñadidoFuncionaAñade salida PDF bilingüe de Chromium sin conexión a las rutas compartidas de#799
report-build de CLI y MCP, validando y saneando el archivo temporal antes de reemplazarlo de forma atómica.
#799 (incidencia en GitHub)AñadidoFuncionaAñade diseños PDF de auditoría técnica autocontenidos en inglés y ruso, con tokens de#798
marca neutros, gráficos de gravedad y cobertura, estados explícitos de ejecución incompleta y flujo de páginas para contenido extenso.
#798 (incidencia en GitHub)CorregidoFuncionaMantiene el diseño del PDF separado de la construcción del modelo de auditoría y de la#798
integración con CLI y MCP.
#798 (incidencia en GitHub)AñadidoFuncionaAñade un modelo de contenido PDF de auditoría técnica, versionado y sin conexión, que#797
conserva los registros de origen, los recuentos exactos de origen y proyectados, el alcance y los estados de cobertura de ambos contratos de auditoría compatibles.
#797 (incidencia en GitHub)CambiadoFuncionaPersiste versiones de escenarios de flujo, contexto de sitio y competencia, evidencia por#796
paso y puertas de revisión…
Persiste las versiones registradas de los escenarios de flujo, el contexto del sitio y de la competencia, la evidencia por paso y las puertas de revisión. Una sesión local posterior solo puede reanudar las ejecuciones interrumpidas si sus dependencias actuales siguen siendo válidas.
#796 (incidencia en GitHub)CambiadoFuncionaExige una lista de trabajo del controlador para iniciar flujos y conserva acuses de#796
triaje de notas de especialista…
Exige una lista de trabajo del controlador para iniciar flujos y conserva acuses explícitos de triaje de notas de especialista para los resultados de tarea, objetivo, competidor, bloqueado o rechazado.
#796 (incidencia en GitHub)CambiadoFuncionaExige que los puntos de control de flujo verifiquen los bytes de los artefactos#796
conservados frente a sus recibos SHA-256…
Exige que los puntos de control de flujo exitosos verifiquen los bytes de los artefactos conservados y vinculados al proyecto frente a sus recibos SHA-256. Si la evidencia falta o ha cambiado, la finalización anterior queda obsoleta sin reescribir el historial; los presupuestos de verificación nunca certifican evidencia en silencio ni descartan su recibo.
#796 (incidencia en GitHub)CambiadoFuncionaPermite perfiles explícitos y acotados de política de hash de evidencia, normalizando las#796
políticas antiguas.
La observación pasiva de flujos comprueba los metadatos de verificación conservados sin volver a calcular el hash de los artefactos; los recibos modificados o no verificados quedan explícitos.
#796 (incidencia en GitHub)AñadidoFuncionaAñade el comando CLI
project progressacotado y paginado y la herramienta MCP#795
#795 (incidencia en GitHub)seo_project_progress, con recuentos por estado de la lista de comprobación y los siguientes elementos accionables. La vista reutiliza los resultados de cobertura con alcance y solo muestra un porcentaje de finalización de tareas de auditoría, claramente etiquetado, cuando cada sitio incluido tiene un plan acordado y un denominador de tareas medido y no vacío. La cobertura de la población de URL se mantiene por separado.CambiadoFuncionaLas listas de comprobación de proyecto ya pueden registrar el alcance de auditoría#794
acordado e informar de cobertura honesta…
Las listas de comprobación de proyecto ya pueden registrar el alcance de auditoría acordado e informar de proporciones de cobertura honestas (#794).
#794 (incidencia en GitHub)project-checklist-inityseo_project_checklist_initaceptan unplanopcional: un revisor, unapopulationde URL declarada comocomplete_set, unasamplecon nombre ounknown, con susource,sizeourlsenumeradas y, si se quiere, poblaciones portemplates, además de un acuerdo opcional detasks(all_agreed, o unaselectioncon IDs de elementos de la lista ya existentes). Todo queda vinculado a la identidad del sitio del proyecto y marcado con la revisión de escritura. Registrar un plan actualiza la lista aseohead.coverage.v3y añade el plan al historial conservado. Volver a registrar un acuerdo idéntico es una operación idempotente sin efecto. Si el acuerdo cambia, la evidencia anterior queda marcada como obsoleta en lugar de reevaluarse con un denominador distinto. Los documentos v3 de plan único se migran al leerlos. Leer, reconciliar o aplicar prioridades nunca actualiza ni inventa una población, y los documentos v1 y v2 siguen cargándose sin cambios. Los elementos fuera de una selección se informan comonot_agreed, visibles fuera de todos los denominadores.CambiadoFuncionaLa finalización de la lista sigue el alcance medido: un elemento automático de sitio con#794
medición parcial…
La finalización de la lista de comprobación ahora sigue el alcance medido. Un elemento automático de ámbito sitio respaldado por una medición limitada (escaneo parcial) sigue sin terminar en lugar de contar como completado, mientras que un elemento acotado a URL de muestra explícitas sí se da por terminado cuando el artefacto cubre exactamente ese alcance. El indicador
#794 (incidencia en GitHub)completede nivel superior ahora significa que la auditoría con alcance está terminada: todas las tareas acordadas aplicables están hechas, no hay exclusiones pendientes y la población de URL acordada está cubierta por completo por mediciones verificadas. Así, un alcance desconocido o no medido nunca puede dar por completada una auditoría.CambiadoFuncionaEl estado de la lista devuelve
coveragecon cinco proporciones separadas:#794audit_tasks,checks…El estado de la lista de comprobación devuelve
#794 (incidencia en GitHub)coveragecon cinco proporciones separadas:audit_tasks,checks(conmeasured_urls),manual_review,deliverable_reviewyurl_population. Cada una tiene su propiobasis,numerator,denominatorystate, de modo que un recuento de URL nunca se mezcla con un recuento de comprobaciones o de tareas. Un denominador que no puede justificarse se queda ennullconstate: "unknown"y un motivo, en lugar de convertirse en 0/0 o en 100 %. Las mediciones que no pueden verificarse frente a la población acordada mantienen el eje de URL enpartialy solo cuentan las URL elegibles verificadas. La pertenencia a URL se verifica con la enumeración acordada, así que una población declarada solo porsizeno cuenta ninguna URL medida, y el numerador nunca puede superar su denominador. Las poblaciones por plantilla se validan como subpoblaciones acordadas de la población del sitio al registrar o leer un plan: las URL enumeradas de una plantilla deben pertenecer al conjunto enumerado del sitio, y la pertenencia declarada a una plantilla nunca puede superar el tamaño acordado del sitio. Un plan incoherente se rechaza, no se recorta ni se cuenta por encima del denominador. La evidencia de comprobación guardada incluye ahora la enumeración de URL medida, de modo que el numerador de URL es un conjunto auditable y no un recuento de filas. La agregación multisitio suma los ejes por sitio y pasa aunknownsiempre que un sitio no pueda justificar su denominador.CambiadoFuncionaUn registro
not_applicablees ahora una exclusión revisada: exige un motivo, un revisor#794y una base de evidencia inspeccionable, es decir, un
#794 (incidencia en GitHub)artifactcon hash y relativo al proyecto, o una referenciaevidenceexplícita. Las exclusiones revisadas conservan su ID estable y su historial, salen de los denominadores de tarea solo mediante esa decisión registrada y se listan por separado enexclusions. Un elemento desactivado, un registro de exclusión obsoleto o un registronot_applicableheredado, escrito antes de la regla de base de evidencia, permanece en el denominador comopending_exclusionhasta que se revise de nuevo. Así, desactivar, retirar del catálogo o reclasificar nunca reduce en silencio los recuentos acordados. Una exclusión revisada nueva sobre un elemento retirado del catálogo se resuelve con normalidad, en lugar de quedarse pendiente para siempre.AñadidoFuncionaAñade el prompt direccionable
workflow/full-audit-v1y el escenariofull-auditpor#793las rutas de catálogo…
Añade el prompt direccionable
#793 (incidencia en GitHub)workflow/full-audit-v1y el escenariofull-audita través de las rutas existentes del catálogo de skills y escenarios de CLI y MCP. El flujo reutiliza las rutas de recopilación y de método ya incluidas, condiciona la verificación y el informe a la evidencia real y separa la preparación del proyecto de la finalización de la auditoría completa.CambiadoFuncionaVincula las decisiones de corrección a artefactos de verificación inmutables y a hashes#792
exactos de evidencia antes y después…
Vincula las decisiones de corrección a artefactos de verificación inmutables y a los hashes exactos de evidencia de antes y de después, incluidas las líneas base de audit.v2 procesadas en flujo.
#792 (incidencia en GitHub)CambiadoFuncionaInforma de los resultados de corrección conservados con estados de cobertura representada#791
y de alcance completo, denominadores por tarea y páginas de casos acotadas para registros de gran tamaño.
#791 (incidencia en GitHub)AñadidoFuncionaAñade reverificaciones de corrección acotadas por registro que reutilizan el verificador#790
protegido, procesan en flujo las selecciones de audit.v2 y rechazan cualquier desvío de alcance.
#790 (incidencia en GitHub)CambiadoFuncionaVincula la verificación de correcciones a la identidad de auditoría conservada y a la#790
política original que afecta a los resultados. Un UUID de escaneo reutilizado por sí solo ya no puede resolver un caso anterior.
#790 (incidencia en GitHub)AñadidoFuncionaAñade el registro de correcciones
ledger.v1(seohead.storage.ledger, identificador de#788aplicación
#788 (incidencia en GitHub)SEOL): un artefacto SQLite separado y vinculado al proyecto que registra hallazgos, la identidad de cada aparición, la pertenencia de URL afectadas y el historial de observaciones de solo adición, a partir de auditoríasscan.v1yscan.v2validadas, sin modificar los escaneos de origen. La ingesta vincula cada origen por UUID de escaneo, revisión de evidencia, hash de auditoría e identidad de productor y configuración. Las réplicas exactas son idempotentes y los bytes en conflicto bajo la misma revisión se rechazan de forma atómica. La coberturacappedyaggregate_only, y la evidenciaunavailable, se conservan como datos y no se tratan en silencio como resueltas. Incluye migración transaccional 0→1, validación completa del esquema y de la integridad al abrir, ydocs/LEDGER.md(#788).AñadidoFuncionaAñade un perfil desechable de proxy inverso TLS en loopback que verifica el aislamiento#787
autenticado de artefactos, la copia de seguridad y la restauración, la caducidad y la reversión atómica de actualizaciones, sin desplegar ningún servicio.
#787 (incidencia en GitHub)CambiadoFuncionaDocumenta los trabajos CLI de SSH de una sola ejecución, los registros de artefactos e#787
incidentes y la recuperación sintética…
Documenta los trabajos CLI de SSH de una sola ejecución, los registros de artefactos e incidentes, la recuperación sintética y el límite separado y futuro para la salud del servicio, el proxy, TLS y el cortafuegos.
#787 (incidencia en GitHub)AñadidoFuncionaAñade el perfil de operador de servicio remoto autoalojado para vinculaciones privadas y#787
salud autenticada…
Añade el perfil de operador de servicio remoto autoalojado para vinculaciones privadas, evidencia de salud autenticada, referencias a archivos de secretos, registros de incidentes, restauración con consistencia SQLite, reversión de versiones y caducidad explícita de los artefactos terminales.
#787 (incidencia en GitHub)AñadidoFuncionaAñade una política de destino remoto vinculada al proyecto para trabajos futuros en cola.#786
Cuando un worker la vincula, valida los destinos y la configuración, vuelve a comprobar el DNS en el momento del envío, fija las solicitudes HTTP y de recursos del navegador, y aplica presupuestos de solicitudes por origen y totales. Los proxies remotos y los backends de navegador alternativos fallan en modo seguro hasta que se demuestre que su salida es segura.
#786 (incidencia en GitHub)AñadidoFuncionaAñade una cola SQLite aislada por proyecto y un worker de escaneo nativo con lease para#785
la API remota opcional…
Añade una cola SQLite aislada por proyecto y un worker de escaneo nativo con lease para la API remota autenticada opcional. Los trabajos conservan los escaneos nativos y los informes JSON y Markdown, admiten envío idempotente, cancelación, recuperación tras fallos al reiniciar, descargas de artefactos con alcance y retención explícita, sin activar ningún listener por defecto.
#785 (incidencia en GitHub)CambiadoFuncionaDefine un contrato opcional, autenticado y versionado de API remota de escaneo, con#784
ajustes de rastreo acotados…
Define un contrato opcional, autenticado y versionado de API remota de escaneo, con ajustes de rastreo nativos y acotados, permisos por proyecto, envío idempotente, esquema OpenAPI y evidencia compatible con el estado del escaneo. Requiere workers duraderos separados y una política de destinos y de salida. Las instalaciones locales de CLI y MCP no cambian (#784).
#784 (incidencia en GitHub)AñadidoFuncionaAñade un runbook SSH de Ubuntu con versión fijada y una prueba de humo del ciclo de vida#783
en Linux desechable que demuestra la instalación, el renderizado de JavaScript, el descubrimiento de artefactos, la actualización, la evidencia de versión y la reversión, sin servicio remoto.
#783 (incidencia en GitHub)CambiadoFuncionaNormaliza la evidencia importada de analítica y búsqueda para cruces con escaneos (#781).#781
#781 (incidencia en GitHub)evidence-normalizelee una exportación CSV, XLSX o JSON suministrada, o un sobreseohead.provider-evidence.v1guardado, totalmente sin conexión, y genera un documento versionadoseohead.normalized-evidence.v1según un manifiesto opcionalseohead.evidence-mapping.v1. Conserva la procedencia de cada campo (del sobre, declarada o desconocida) para la fuente, la identidad del informe, el periodo, la zona horaria, la atribución, el motor, la cobertura de recopilación y el vínculo con URL. Un valor medido0sigue siendo cero. Las filas ausentes, las celdas nulas o en blanco, las celdas con fórmula, los valores suprimidos, los periodos no recopilados y la recopilación fallida u omitida siguen como no disponibles de forma explícita.evidence-joinune la evidencia normalizada con una lista de escaneo, auditoría o páginas según la política estricta de clavesexternal_join.v1, con relajaciones explícitas únicamente. Conserva las poblaciones coincidentes, solo rastreadas, solo externas y no vinculables en su granularidad declarada, e informa de las colisiones de claves en lugar de multiplicar filas.--comparejunto con una política declarada añade una decisión pura de compatible, incompatible o desconocido según el periodo, el límite de zona horaria, la identidad, la atribución, el motor y la granularidad. Además, informa de la elegibilidad de cuadrantes con cero medido para el trabajo posterior de cohortes. Las fuentes restringidas mantienen filas e identificadores dentro de un artefacto local privado y devuelven solo recuentos.AñadidoFuncionaAñade una experiencia de preparación de proveedores sin conexión con referencias de#780
credenciales redactadas…
Añade una experiencia de preparación de proveedores sin conexión, con referencias de credenciales redactadas, esquemas de rutas de operación, metadatos de cuota y privacidad, y estados explícitos de acceso al destino. La mera presencia de una credencial nunca verifica el permiso.
#780 (incidencia en GitHub)CambiadoFuncionaAmplía
seohead watchhasta convertirlo en un observador de proyecto de solo lectura con#775navegación por hallazgos…
Amplía
#775 (incidencia en GitHub)seohead watchhasta convertirlo en un observador de proyecto de solo lectura, con navegación por hallazgos conservados, detalle de evidencia, estado de vistas guardadas y de revisión, y avisos de bandeja de MCP con alcance explícito.AñadidoFuncionaAñade entrega autorizada de informes sintéticos con recibos de idempotencia persistentes#773
y reinicio seguro…
Añade entrega autorizada de informes sintéticos con recibos de idempotencia persistentes y un comportamiento de reinicio seguro ante reintentos.
#773 (incidencia en GitHub)CambiadoFuncionaConserva las reclamaciones de entrega inciertas tras una salida del proceso o una#773
confirmación de documento malformada, evitando una segunda subida automática cuando no pueda establecerse la aceptación.
#773 (incidencia en GitHub)CambiadoFuncionaMide las vistas previas de informes a partir de la evidencia conservada, con tamaño#772
renderizado y hash de origen…
Mide las vistas previas de informes a partir de la evidencia conservada, incluidos el tamaño renderizado, el hash de origen, los recuentos de población, la cobertura y el perfil. Informa de los renderizadores ausentes y de las entradas demasiado grandes antes de enviar. Ajusta el presupuesto de JS del asistente completo al contrato de cola compartido.
#772 (incidencia en GitHub)CambiadoFuncionaConserva las identidades exactas de envío del bot confirmadas tras caídas de cola o de#771
propiedad…
Conserva las identidades exactas de envío del bot confirmadas tras caídas de la cola o de la propiedad, deduplica las actualizaciones de confianza y aísla el estado, la cancelación, la recuperación y la entrega por actor o chat que inicia cada trabajo. Las repeticiones intencionales e idénticas siguen siendo trabajos separados.
#771 (incidencia en GitHub)CorregidoFuncionaRestaura el último trabajo confirmado de actor y chat tras reiniciar el servicio,#771
conservando la cancelación…
Restaura el último trabajo confirmado de actor y chat tras reiniciar el servicio, conservando el comportamiento de cancelación y de reejecución tras una nueva confirmación, sin reanudar un borrador no confirmado.
#771 (incidencia en GitHub)AñadidoFuncionaAñade el paquete de evidencias de revisión de software para autoalojamiento, revisión#761
legal y compras (#761).
#761 (incidencia en GitHub)scripts/generate_review_pack.pygenera y verifica un inventario versionado de dependencias y licencias, con un perfil por grupo de instalación, versiones resueltas y fuentes de licencia medidas en el entorno de generación. Los requisitos excluidos por marcador, no satisfechos por la especificación o no instalados se registran en lugar de descartarse. Además genera un documento de procedencia a nivel de versión que vincula las distribuciones compiladas con una etiqueta y con la revisión de origen del manifiesto de compilación incrustado, y unSHA256SUMS.txtque cubre todo lo anterior. La generación rechaza una etiqueta que no coincida conpyproject.toml. La verificación vuelve a comprobar formatos y hashes registrados, reextrae cada distribución para revalidar su manifiesto incrustado, el nombre y la versión que declara su nombre de archivo, y los camposNameyVersionde su propio*.dist-info/METADATAoPKG-INFOfrente apyproject.toml, sin confiar en el registro. Un escaneo de centinelasSEOHEAD_REVIEW_CANARY_*demuestra que los archivos del paquete y los diagnósticos no contienen credenciales ni marcas de cliente sembradas. La CI regenera y verifica el paquete con una etiqueta desechable en cada ejecución. El flujo de publicación lo verifica y lo adjunta a una versiónv*real.AñadidoFuncionaAñade
docs/SOFTWARE_REVIEW.md: el mapa de endpoints salientes y de flujos de datos (a#761qué llama cada función, qué envía y si la llamada es opcional), el límite entre local y remoto, el almacenamiento de credenciales y artefactos, el estado de la telemetría, la notificación de seguridad y el estado de mantenimiento, y cómo revisar los cambios de cada versión. Enlaza los runbooks de instalación y despliegue en lugar de duplicarlos (#783, #787).
#761 (incidencia en GitHub)AñadidoFuncionaAñade una comprobación previa sin conexión de capacidad y sumas de control para Google#760
Sheets…
Añade una comprobación previa sin conexión de capacidad y de sumas de control para Google Sheets, destinada a paquetes BI locales completos. No hace ninguna solicitud a Google ni escribe en ninguna hoja de cálculo.
#760 (incidencia en GitHub)AñadidoFuncionaAñade un transporte explícito de reemplazo para Google Sheets con lista de permitidos y#760
asignaciones por conjunto de datos…
Añade un transporte explícito de reemplazo para Google Sheets con lista de permitidos, asignaciones de hoja por conjunto de datos, preparación y relectura acotadas, y una única publicación atómica solo de valores que conserva los ID de hoja existentes.
#760 (incidencia en GitHub)CambiadoFuncionaRegistra la preparación de Google Sheets en un punto de control antes de crear hojas#760
remotas…
Registra la preparación de Google Sheets en un punto de control antes de crear cualquier hoja de preparación remota, y concilia una respuesta de inicio perdida mediante sus identidades deterministas de hoja de preparación antes de reintentar.
#760 (incidencia en GitHub)CambiadoFuncionaConserva valores tipados y relecturas dispersas de Google, rechaza hojas de destino#760
duplicadas…
Conserva los valores numéricos y booleanos tipados y las relecturas dispersas de Google, rechaza destinos de hoja duplicados y la deriva del contrato de conjuntos de datos, vincula la recuperación al destino exacto configurado y conserva la preparación reanudable tras agotar la cuota. Presupuesta el crecimiento de la cuadrícula de destino antes del reemplazo atómico e informa de los recuentos de filas no confirmados en las ejecuciones interrumpidas.
#760 (incidencia en GitHub)CambiadoFuncionaValida complementos de grupo completos y vinculados al origen antes de escribir en#760
destino…
Valida los complementos de grupo completos y vinculados al origen antes de escribir en el destino, los conserva junto con los hallazgos seleccionados e informa en los recibos de destino y del libro de cálculo de que las referencias de pertenencia son solo locales, sin afirmar que el complemento se haya subido.
#760 (incidencia en GitHub)CambiadoFuncionaDivide los conjuntos grandes de registros de
scan-exporten XLSX en hojas numeradas y#759una hoja Partitions…
Divide los conjuntos grandes de registros de
#759 (incidencia en GitHub)scan-exporten XLSX en hojas numeradas y deterministas, con una hoja Partitions que conserva el número de filas, en lugar de fallar al llegar al límite de filas por hoja de Excel.CambiadoFuncionaDivide las hojas Findings y Pages de
report-builden el límite de filas de Excel y#759emite un índice con hash…
Divide las hojas Findings y Pages de
#759 (incidencia en GitHub)report-builden el límite de filas de Excel y emite un.xlsx.index.jsoncon hash, que incluye los rangos exactos de registros, la población de origen y las referencias de selección y de cobertura. Conserva el informe anterior ante fallos de escritura capturados y limpia los spools de streaming al interrumpirse.CambiadoFuncionaRechaza celdas XLSX de más de 32 767 caracteres antes de que la biblioteca las trunque…#759
Rechaza celdas XLSX de más de 32 767 caracteres antes de que la biblioteca de hojas de cálculo pueda truncarlas, protege los metadatos de Summary frente a la inyección de fórmulas y rechaza filas de auditoría conservadas malformadas antes de que una exportación incompleta pueda declararse correcta. Las exportaciones CSV y JSON completas y la política acotada de resumen en PDF siguen disponibles.
#759 (incidencia en GitHub)AñadidoFuncionaAñade entrega acotada de CSV de BI seleccionado con contabilidad exacta de filas de#759
origen, seleccionadas y omitidas…
Añade entrega acotada de CSV de BI seleccionado, con contabilidad exacta de filas de origen, seleccionadas y omitidas, cobertura de origen conservada, hashes calculados en flujo y un índice durable de rangos de CSV a hoja de XLSX. Las celdas de Excel demasiado grandes fallan antes de truncarse, y una salida interrumpida no se marca como completa.
#759 (incidencia en GitHub)CambiadoFuncionaConserva filas completas e inmutables de cobertura de comprobaciones junto a las#759
exportaciones BI de hallazgos seleccionados, incluidos los motivos de las comprobaciones omitidas, y admite la selección exacta de hallazgos por segmento conservado del alcance de rastreo.
#759 (incidencia en GitHub)AñadidoFuncionaAñade diagnósticos de rastreo sin conexión para escaneos nativos guardados y artefactos#758
de ejecuciones antiguas…
Añade diagnósticos de rastreo sin conexión para escaneos nativos guardados y artefactos de ejecuciones heredadas, con evidencia de decisión acotada, explicaciones accionables, acceso de solo lectura por CLI y MCP, y un comando o herramienta de exportación redactada aparte, de activación voluntaria.
#758 (incidencia en GitHub)AñadidoFuncionaAñade vistas versionadas de hallazgos de proyecto con filtros cerrados y orden por#757
gravedad…
Añade vistas versionadas de hallazgos de proyecto con filtros cerrados, ordenación por gravedad, proyección de columnas y paginación acotada. Al ordenar por gravedad descendente, los hallazgos críticos aparecen primero; en orden ascendente va de aviso a crítico. CLI, MCP, los informes y la futura navegación en terminal pueden reutilizar la misma vista de solo lectura sin cambiar la evidencia de origen, la puntuación, las tareas ni la cobertura.
#757 (incidencia en GitHub)AñadidoFuncionaAñade planificación de monitorización local, desactivada por defecto, con presupuestos#756
incrementales y completos…
Añade planificación de monitorización local, desactivada por defecto, con presupuestos explícitos incrementales y de actualización completa, rechazo de solapamientos, reclamaciones de recuperación, procedencia inmutable de observaciones, retención de resultados parciales y alertas y avisos de recuperación deduplicados. El monitor no inicia ningún temporizador, rastreo ni canal de entrega.
#756 (incidencia en GitHub)AñadidoFuncionaAñade un adaptador de entrega de servicio inyectado y explícito para avisos completos de#756
monitor conservados.
Requiere un destino autorizado y vinculado al proyecto, además de un almacén de recibos duradero. No se activa por defecto ningún transporte, cuenta, temporizador ni destino.
#756 (incidencia en GitHub)CambiadoFuncionaHace seguras ante reinicios las reclamaciones de monitorización, la cobertura y la#756
procedencia de caché…
Hace seguras ante reinicios las reclamaciones de monitorización conservadas, la cobertura, la procedencia de caché, la evidencia de recuperación derivada y la entrega opcional de servicio.
#756 (incidencia en GitHub)AñadidoFuncionaAñade un recolector de monitor de una sola ejecución, explícito y acotado por lease, con#756
evidencia consciente de la caché…
Añade un recolector de monitor de una sola ejecución, explícito y acotado por lease, con evidencia conservada que tiene en cuenta la caché y recibos de entrega solo locales.
#756 (incidencia en GitHub)AñadidoFuncionaAñadidos
verify-fixes/seo_verify_fixespara volver a comprobar URL seleccionadas#755Añadido
#755 (incidencia en GitHub)verify-fixes/seo_verify_fixespara volver a comprobar, de forma acotada, URL seleccionadas a partir de IDs de incidencias guardados, de una vista de verificación o de una lista explícita de URL. Reutiliza la política de rastreo registrada y escribe un artefacto de verificación independiente, que no sobrescribe nada, con su informe enfocado. Distingue entre incidencias resueltas, persistentes, cambiadas y no verificables. Una auditoría after existente solo puede verificarse sin acceso a la red si tiene un UUID de escaneo propio y una hora de observación registrada posterior; las mediciones no realizadas o la evidencia de todo el sitio nunca se marcan como corregidas.CambiadoFuncionaFiltrado de rutas nativas por extensión y Content-Type antes de procesarlas#749
Los rastreos nativos por URL pueden filtrar las rutas descubiertas por la extensión final del nombre de archivo antes de hacer peticiones, y por el
#749 (incidencia en GitHub)Content-Typereal de la respuesta antes de analizarla o conservar el cuerpo. Ambas fases de filtrado registran sus decisiones y conservan la evidencia de enlaces, estados, cabeceras y redirecciones; los metadatos HTML de las páginas filtradas siguen marcados explícitamente como no medidos. Los recursos de scripts y hojas de estilo mantienen su selección y sus presupuestos de bytes independientes.CambiadoFuncionaCobertura explícita cuando no hay cuerpo HTML disponible#749
Cuando no hay cuerpo HTML disponible, las incidencias que dependen del cuerpo conservan ahora una cobertura omitida explícita, en lugar de tratar los valores por defecto del parser como limpios o como metadatos ausentes observados.
#749 (incidencia en GitHub)AñadidoFuncionaExclusiones auditables por patrón de URL en las incidencias#748
Las incidencias suprimidas se mantienen en el JSON de auditoría y en las exportaciones de report-build, con la regla que coincide y el motivo, mientras que los totales de incidencias activas, la puntuación y el backlog de tareas reflejan la política configurada. Los artefactos de escaneo nativos conservan la política para el reanálisis sin conexión; el número de reglas y la longitud de los campos están acotados.
#748 (incidencia en GitHub)AñadidoFuncionaAñadido
scan-export(seo_scan_export): exportación offline de datos de escaneo#747Añade
#747 (incidencia en GitHub)scan-export(seo_scan_export): una exportación de datos de escaneo de solo lectura y sin conexión, bajo el contrato versionadoscan_export.v1. Lee un artefacto SQLitescan.v1validado o unaudit.jsonde SF Analyzer, y escribe CSV (un archivo por tipo de registro más un manifiesto), XLSX (libro de solo escritura), un envoltorio JSON en streaming o un documento XML documentado. Cada salida incluye procedencia, número de filas exportadas, estadísticas de ejecución y cobertura explícita (qué comprobaciones se ejecutaron, se omitieron, se desactivaron o quedaron sin contabilizar), y ninguna de ellas puede eliminarse con la selección de campos.--recordsy--fieldsofrecen una proyección validada de los registros de página, enlaces e incidencias; los tipos de registro o nombres de campo desconocidos se rechazan antes de crear cualquier archivo de salida. Los valores ausentes se mantienen explícitos (nullen JSON,state="absent"en XML,\Nen CSV/XLSX) en lugar de convertirse en ceros inventados. La salida XML es una serialización generada con escape UTF-8 correcto; nunca interpreta XML, DTD, hojas de estilo ni entidades aportadas por el usuario. CSV y XLSX mantienen la defensa existente contra inyección de fórmulas; XLSX rechaza los desbordamientos de filas, columnas y texto de celda de Excel en lugar de truncar, y cualquier fallo de serialización no deja ningún artefacto parcial que parezca válido.CambiadoFunciona
crawl-sitecomprueba de forma opcional los destinos externos registrados#746
#746 (incidencia en GitHub)crawl-siteañade una comprobación opcional y acotada de los destinos externos registrados:discovery.external.crawlejecuta una fase separada tras cerrar la frontera interna, y pide cada destino de enlace saliente distinto una sola vez, con sus propios presupuestosexternal_checks.max_targets/max_hosts/max_requests/max_depth/max_redirects; nunca hay recorrido recursivo fuera del host. Los resultados (obtenido, fallido, bloqueado u omitido con la regla que lo rechazó) se añaden aexternal_checks.jsonlen el directorio de ejecución, conservan la procedencia de la página de origen, persisten al reanudar sin reabrir presupuestos agotados e informan de su propia cobertura endiscovery.external_checks, separada de la completitud del rastreo interno. Requierediscovery.external.store; se rechaza explícitamente en la ruta SQLite nativa (--scan-out) hasta que ese colector incorpore esta fase.AñadidoFuncionaProxy HTTP de reenvío con política explícita y validada para el rastreo nativo#745
Añade una política explícita y validada de proxy HTTP de reenvío para el rastreo nativo, que cubre las peticiones de páginas, sitemaps, recursos y del navegador fijado, con procedencia de ruta redactada.
#745 (incidencia en GitHub)CambiadoFuncionaEl renderizado nativo permite elegir el motor del navegador#744
El paso de renderizado del rastreador nativo expone ya su navegador mediante configuración, en lugar de tener Chromium fijo en el código.
#744 (incidencia en GitHub)rendering.browser.engineeligechromium(sigue siendo el valor por defecto),firefoxowebkita través de la misma ruta protegida de Playwright. Un nombre desconocido falla al validar la configuración, no al lanzar el navegador, y un motor solicitado cuyo binario no está instalado informa de un error de dependencia que indica la solución (playwright install <engine>), en lugar de caer en silencio a Chromium. La limitación documentada de Firefox se aplica de forma honesta: rechazarendering.browser.mobile_emulation(is_mobileno se soporta allí), mientras que la opción independienterendering.browser.touch_emulation(has_touch) sigue llegando al contexto. Las sondas y los renderizados completos comparten una única configuración efectiva, así que un patrón nunca se escala con un navegador distinto del que generó su evidencia.CambiadoFunciona
rendering.browser.viewport_widthyrendering.browser.viewport_heightañaden viewports#744a medida
#744 (incidencia en GitHub)rendering.browser.viewport_widthyrendering.browser.viewport_heightañaden dimensiones de viewport arbitrarias junto a los presets existentesdesktop/mobile, que siguen determinando el perfil como antes. El par es de todo o nada y está acotado a 1..16384 px; un par personalizado reemplaza solo las dimensiones del preset y no implica emulación móvil ni táctil, que siguen siendo indicadores explícitos que debe establecer quien opera.CambiadoFunciona
rendering.browser.page_concurrencylimita las peticiones de navegador en vuelo#744
#744 (incidencia en GitHub)rendering.browser.page_concurrencylimita cuántas peticiones de navegador pueden estar en vuelo durante la escalada, por separado despeed.concurrency, que sigue regulando la cortesía del rastreo HTTP. El valor por defecto, 1, conserva el comportamiento secuencial y no crea ningún pool; por encima de 1, las sondas y los renderizados se ejecutan en un pool de workers acotado, mientras que cada veredicto, confirmación y escritura en SQLite se mantiene en el hilo orquestador y en el orden de envío. El plazo de renderizado, el presupuesto de URL y las políticas de muestreo y completas se mantienen con concurrencia; un lote detenido espera a las páginas que ya inició y nunca programa nuevas; los workers interrumpidos o fallidos no dejan ningún hilo, página, contexto ni navegador activos tras la llamada.CambiadoFuncionaEl motor, su versión y el viewport efectivo quedan registrados en el manifiesto#744
El motor seleccionado, su versión real informada, el viewport efectivo y la concurrencia de página configurada se registran en el manifiesto del rastreo, en su huella y en la procedencia del renderizador de cada documento renderizado, incluidos los intentos fallidos, que registran lo solicitado sin inventar un renderizado correcto. Ambas rutas de escalada respetan la configuración: el rastreo por directorio y el escaneo nativo SQLite, donde los candidatos de enlaces renderizados entran en la frontera mediante la admisión deduplicadora existente una vez activo
#744 (incidencia en GitHub)rendering.rendered_links.crawl.AñadidoFuncionaComprobaciones opcionales de canonical para patrones de paginación y filtros#727
Añade comprobaciones opcionales de la política canonical para los patrones de URL de paginación y de filtros configurados, tanto en el pipeline de exportación de SF como en el de auditoría del rastreo nativo. Las reglas de paginación admiten como destino la propia página, la primera página o la página de aterrizaje; las reglas de filtros admiten la propia página o la página de aterrizaje. Las políticas ausentes y los destinos que no aparecen en la evidencia del rastreo siguen sin medir, y las comprobaciones de código de estado del destino se mantienen separadas.
#727 (incidencia en GitHub)AñadidoFuncionaArchivos reanudables de GSC Search Analytics en el histórico local de proveedores#718
Añade archivos reanudables de GSC Search Analytics en el almacén SQLite local compartido de histórico de proveedores, accesibles de forma coherente mediante
#718 (incidencia en GitHub)gsc-archiveyseo_gsc_archive. El estado sin conexión, la preparación explícita, la recogida acotada y las instantáneas verificadas comparten un mismo núcleo.CambiadoFuncionaProcedencia de proveedor y motor, métricas que pueden ser nulas y reintentos acotados#718
Conserva la procedencia de proveedor y motor y las métricas que pueden ser nulas, encola solo los rangos de disponibilidad sin cubrir y persiste las esperas por cuota y los reintentos transitorios acotados.
#718 (incidencia en GitHub)AñadidoFuncionaHistórico SQLite local y versionado para GA4, Metrika, GSC y Yandex Webmaster#716
Añade un histórico SQLite local y versionado para los datos diarios de GA4, Metrika, consultas y páginas web de GSC y Yandex Webmaster, con reemplazo atómico por día y cobertura explícita: solicitado, vacío, parcial, fallido y con retraso.
#716 (incidencia en GitHub)AñadidoFuncionaSincronización acotada, estado offline y exportación JSON/CSV en la CLI y el MCP#716
Expone la sincronización acotada y determinista, el estado sin conexión y la exportación JSON/CSV a través de la CLI compartida y del MCP local, incluidas la aditividad de métricas y los metadatos conservadores de zona horaria. No se almacenan credenciales ni datos de proveedores en el repositorio.
#716 (incidencia en GitHub)CambiadoFuncionaEl modo A de SF verifica las exportaciones antes de analizar#715
El modo A de SF verifica ahora las capacidades de exportación que solicita la CLI instalada y exige un conjunto completo y reciente de exportaciones antes de analizar. La procedencia del perfil completo registra el manifiesto de exportación verificado y la lectura de la velocidad de rastreo; un límite de velocidad explícito falla antes de rastrear si su configuración base falta o no es válida.
#715 (incidencia en GitHub)CambiadoFuncionaReintentos por tramos mensuales en
metrika-report(seo_metrika_report) y#714MetrikaClient.report()
#714 (incidencia en GitHub)metrika-report(seo_metrika_report) yMetrikaClient.report(): un rechazo de la Reporting API por «Query is too complicated» se reintenta ahora por tramos mensuales, con una espera de 5 a 15 s; un tramo que sigue rechazándose se vuelve a enviar conaccuracy=0.1muestreado. Solo se combinan las métricas demostrablemente aditivas sobre periodos disjuntos (ym:s:visits,ym:s:pageviews): una consulta de visitantes únicos, porcentajes, medias o métricas no verificables se rechaza antes de la primera petición de tramo, en lugar de devolver un valor sumado que sería incorrecto. Los tramos se combinan a medida que llegan bajo un único límite global de filas que también acota las descargas: una vez agotado, las particiones restantes nunca se piden y sus intervalos de fechas se nombran ensplit.unfetched; un tramo interrumpido a mitad lista su propio intervalo allí conpartial. Los totalestotal_rows/totalsde todo el periodo siguen desconocidos cuando los periodos no consultados los hacen incognoscibles, y la ventana devuelta se marca como parcial. Las respuestas combinadas vuelven a aplicar elsortde quien llama (dimensiones y métricas, o el orden por defecto de la API: primera métrica descendente), y la ventanaoffset/limitse toma del conjunto global combinado. Los campos de muestreo reflejan lo que la API informó realmente (sampled, peorsample_share); un tramo que no los informa deja el valor de todo el periodo como desconocido:nullen la respuesta de CLI/MCP, nunca unfalseinventado.contains_sensitive_dataes el OR de los tramos,min/maxse recalculan sobre las filas combinadas, y las celdas o totales de métricas ausentes o malformados marcan el cuerpo comoincompleteen lugar de leerse como cero. El bloquesplitconserva los periodos solicitados y resueltos, la zona horaria usada y, por tramo, la precisión, los intentos, las filas descartadas y los metadatos de muestreo; una partición que falla nombra los intervalos completados y las precisiones agotadas. Las fechas relativas (today,NdaysAgo) se resuelven en latimezonede la petición o en la zona del propio contador (time_zone_name, o si no su desfase en minutos), nunca en la fecha del host. Un periodo que no puede convertirse en fechas (un atajo comomonth) se sigue reintentando y muestreando antes de relanzar el error. Unaaccuracyexplícita se respeta en todas las formas documentadas (low/medium/high/fullo una proporción numérica como"1"): cualquier valor por encima del último recurso de muestreo mantiene el fallbackaccuracy=0.1, mientras que un ajuste ya más bajo de quien llama (lowo una proporción igual o inferior) se conserva en lugar de remuestrearse hacia arriba. Cada petición intentada, incluida la llamada global rechazada, llega al diario de gasto.CambiadoFuncionaYandex Webmaster: la operación
indexingusa el endpoint v4 real#713Yandex Webmaster: la operación
#713 (incidencia en GitHub)indexinglee ahora el endpoint real v4/indexing/samplesen lugar del inexistente/search-urls; la nuevabroken_links_sampleslee/links/internal/broken/samples, y la paginación respeta el límite de tamaño de página documentado de cada endpoint (500 para consultas, 100 para las listas de muestras), en lugar de enviarlimit=500en todas partes (#713).CambiadoFuncionaYandex Webmaster valida el
county la forma de cada página#713La recogida paginada de Yandex Webmaster valida ahora el
#713 (incidencia en GitHub)countdocumentado de cada página y la forma de su lista, incluido uncountmenor que las filas devueltas. Pide en cada página como máximo el presupuesto de filas restante, de modo que un corte pormax_rowsnunca lea de más y produzca uncompletefalso; exponereturned/truncatedpara una única página no paginada como un fragmento acotado; informa departialsiempre que queden filas sin leer, y falla las páginas malformadas en lugar de afirmar un resultado vacío y completo (#713).CambiadoFuncionaRender-check usa la confianza de la plataforma más una CA explícita#709
Render-check usa la confianza de la plataforma más una CA seleccionada explícitamente, reproduce las subpeticiones POST fijadas e informa de los fallos de verificación de certificados sin detalles del transporte.
#709 (incidencia en GitHub)CambiadoFuncionaReconoce el fallo TLS del proxy fijado y verifica la CA de fixture explícita#709
Reconoce el fallo de verificación TLS del transporte proxy fijado y verifica, mediante un interceptor CONNECT sintético propio, la confianza explícita en la CA de fixture, la repetición de POST, los límites de respuesta y el rechazo de destinos privados, sin cambiar la confianza de la plataforma.
#709 (incidencia en GitHub)
3 de octubre de 2026
5 añadido8 cambiado1 corregidoAñadidoFuncionaAñadido
crawl-importpara paquetes CSV de rastreos de terceros con mapeo explícito#819Añade
#819 (incidencia en GitHub)crawl-importpara paquetes CSV de rastreos de terceros con mapeo explícito. Conserva la identidad de la fuente externa, la cobertura por campo, las observaciones duplicadas y los datos no disponibles enthird_party_crawl.v1, sin tratar el resultado como un escaneo nativo ni como una auditoría de SF.AñadidoFuncionaTransporte remoto opcional de Playwright con endpoint y versión explícitos#808
Añade un transporte remoto opcional de navegador Playwright con endpoint explícito y comprobaciones de versión, estados de fallo seguros y ningún recurso de lanzamiento local, manteniendo los valores por defecto del renderizado local.
#808 (incidencia en GitHub)AñadidoFuncionaConsultas de ruta observada más corta y de enlaces entrantes inversos#805
Añade consultas Python de solo lectura, acotadas y deterministas, para la ruta observada más corta y los enlaces entrantes inversos sobre los enlaces de escaneo conservados, con la identidad del registro de escaneo en cada salto y cobertura explícita de grafo parcial.
#805 (incidencia en GitHub)CambiadoFuncionaRegresión de enrutamiento de proveedores alineada con la petición Wordstat de Arsenkin#779
Alinea la regresión de enrutamiento de proveedores con el contrato corregido de la petición de frecuencia Wordstat de Arsenkin (#720, #779).
#779 (incidencia en GitHub)AñadidoFuncionaAñadido
docs/PROVIDERS.md: matriz generada de capacidades de proveedores#779Añade
#779 (incidencia en GitHub)docs/PROVIDERS.md, una matriz generada de capacidades de proveedores y de flujos de trabajo especializados (#779, épica #753). Se genera a partir del registro de proveedores activo y de un catálogo curado de flujos enseohead/core/provider_matrix.py, mediantescripts/generate_provider_matrix.py. Registra, por flujo, los comandos disponibles, la autenticación, el coste y la cuota, la clase de privacidad, las limitaciones y el fallback CSV medianteprovider-join. Los estados distinguen entre soportado, parcial, no soportado y no verificado; ningún proveedor declarado aparece como verificado en vivo, el trabajo explícitamente no soportado se lista por nombre, y la primera versión se selecciona por fases sin afirmar que cubre todos los servicios. Las discrepancias entre el documento confirmado y los registros las detectantests/test_docs_drift.pyytests/test_provider_matrix.py.CorregidoFuncionaCorregido
keywords-exact/seo_keywords_exact, que nunca devolvía resultados#720Corregido
#720 (incidencia en GitHub)keywords-exact/seo_keywords_exact, que nunca podía devolver un resultado: la tarea se creaba para una herramienta de Arsenkin llamadakeywords_frequencyque no existe, así que cada llamada respondía404 WRONG_TOOL. El!Wexacto va ahora a la herramientawordstatcontype=1, el array de frases bajoqueriesy la región como lista de un solo elemento.CambiadoFuncionaPide el selector
overalpara!W: los valoreswsde Arsenkin son operadores distintos#720Solicita el selector
#720 (incidencia en GitHub)overalpara!W: los valoreswsde Arsenkin son operadores distintos.basees amplio (WS),quotedes la frase entre comillas («WS»),overales la forma exacta de palabra (!WS) que pide!W, yexactes la forma de orden estricto ([!WS]).CambiadoFuncionaElimina antes de enviar la puntuación que el proveedor rechaza, como el
/#720Elimina antes de enviar la puntuación que el proveedor rechaza: una sola frase con
#720 (incidencia en GitHub)/o comillas hacía que rechazara todo el lote con422 JSON_VALIDATION_ERROR. Las frases reescritas se devuelven encleaned, para que quien llama vea cuáles se midieron en otra forma.CambiadoFuncionaDevuelve
frequenciescomo{phrase: {"base": N, "overal": N}}junto a la respuesta#720bruta del proveedor. Una frase cuyo resultado solo nombra otras regiones se omite y se lista en
#720 (incidencia en GitHub)warnings, en lugar de tomar prestadas las cifras de otra región.AñadidoFuncionaAcceso de solo lectura a Topvisor desde la CLI y el MCP#719
Añade acceso de solo lectura y acotado a Topvisor a través de la CLI compartida y del handler MCP, con archivos de credenciales centralizados, paginación explícita y sin operaciones de pago por comprobación.
#719 (incidencia en GitHub)CambiadoFuncionaAlinea el bloque
sources.gscdesources-doctorconprovider_status.gsc#717Alinea el bloque heredado
#717 (incidencia en GitHub)sources.gscdesources-doctorconprovider_status.gsc:readyy el nuevo campocomponentsahora salen de los mismos componentes de credencial (token bearer de OAuth, concesión duradera o cuenta de servicio), en lugar de mirar solo el archivo bearer. Por eso una cuenta de servicio configurada ya no aparece como «GSC no está configurado». El componente de cuenta de servicio valida ahora el propio documento JSON (archivo regular privado, tamaño acotado, tiposervice_account, la URI de token de Google exacta y los campos obligatorios), y ambos bloques de doctor informan de un valor seguroservice_account_status(missing,unsafe_file,too_large,unreadable,malformed_json,unsupported_shapeoconfigured_unverified). Así, un archivo demasiado grande, ilegible o malformado se distingue de uno configurado pero sin verificar, sin exponer su contenido.CambiadoFunciona
crawl-sitemarcafinished_aty el ciclofinishedcuando la cola termina#712Los artefactos de escaneo de
#712 (incidencia en GitHub)crawl-siteregistran ahorafinished_aty un ciclo de vidafinishedcuando cada fila de frontera aceptada alcanza un estado terminal, incluidas las ejecuciones cuya evidencia conservada es parcial:crawl_partialya nombra las observaciones omitidas, así que una cola vaciada ya no aparece como captura interrumpida enscan-status,scan-listni en el histórico (#712). Una ejecución detenida explícitamente —abortada antes de aceptar trabajo, cancelada o detenida por el circuito de errores— conservainterruptedy su motivo registrado incluso después de vaciar la cola, también a través deresume_or_finalize, de modo que las rutas de parada nunca reciben una marca de finalización falsa.CambiadoFunciona
duplicate-check --scanyboilerplate-report --scanprocesan corpus de tamaño normal#710
#710 (incidencia en GitHub)duplicate-check --scanyboilerplate-report --scanahora procesan en streaming un corpus conservado en lugar de fallar en sitios de tamaño normal: el plazo de apertura y validación del escaneo se calcula según el tamaño del artefacto, y cada lectura de documento tiene su propio plazo, de modo que un corpus de 1500 páginas ya no termina eninterrupted. El presupuesto de bytes de entrada del corpus mide lo que el analizador retiene realmente (Markdown extraído para duplicados, un digest por página para el boilerplate), no el tamaño del HTML bruto; al alcanzar un límite del corpus se informa cobertura parcial con los recuentos exactos de preparados y elegibles, y el límite que detuvo la lectura (#710).CambiadoFunciona
report()yby_time()de Metrika rechazanoffset < 1en local con unValueError#707
#707 (incidencia en GitHub)report()yby_time()de Metrika rechazan ahoraoffset < 1en local con unValueError, en lugar de reenviarlo a la Reporting API, que respondeoffset=0con HTTP 400. Nuevas pruebas sin conexión fijan el contrato base 1 enmetrika-report,seo_metrika_reportyaggregate_reportdeprovider-collect, y verifican que las condiciones de parada paginadas (total_rows,ROW_CAP) cuentan las filas saltadas antes de unoffsetno predeterminado (#707).
2 de octubre de 2026
1 añadido2 cambiadoCambiadoFunciona
metrika-traffic-pdfen macOS: Chrome ya no bloquea la generación del PDF#731
#731 (incidencia en GitHub)metrika-traffic-pdfen macOS: Chrome escribe el PDF y sigue ejecutándose; el navegador ahora se inicia sin esperar y se detiene una vez verificado el PDF.CambiadoFuncionaYandex Webmaster:
user_idsale del token y hay nuevas operaciones de solo lectura#713Yandex Webmaster:
#713 (incidencia en GitHub)user_idse resuelve a partir del token; nuevas operaciones de solo lecturasummary,diagnostics,sqi_history,search_history,query_history,in_search_history,events_history,indexing_history,important_urls,broken_links_history,external_links_history;paramspara fechas e indicadores; paginación de las listas de consultas y de muestras de rastreo (#713).AñadidoFuncionaNueva skill técnica
traffic-report: informe de tráfico mensual o anual para el clienteNueva skill técnica
traffic-report: un informe mensual o anual para el cliente a partir de Metrika, Webmaster y Search Console (conversiones contadas como visitas, comprobaciones de coherencia de objetivos, productos, retrato del comprador y reglas para las diapositivas).
1 de octubre de 2026
1 añadido1 cambiadoAñadidoFuncionaAñadido
metrika-traffic-pdf(seo_metrika_traffic_pdf): informe de tráfico en PDF#731Añade
#731 (incidencia en GitHub)metrika-traffic-pdf(seo_metrika_traffic_pdf): un informe de tráfico estático en A4 apaisado, con el diseño de un panel analítico, generado a partir de Yandex Metrika. La recogida y el renderizado son etapas separadas. La recogida lee la Reporting API (unas 40 peticiones sin coste, de solo lectura) y la agrupa en un único documentoseohead.metrika-traffic/1: nueve tarjetas de KPI (usuarios, visitas, páginas vistas, páginas por visita, visitas por día, porcentaje de rebote, duración media de la visita, porcentaje de visitantes con dos o tres visitas y porcentaje de visitantes nuevos), con variaciones respecto al periodo anterior de igual duración y a las mismas fechas un año antes; la dinámica diaria; ventanas de 3, 6 y 12 meses frente a las ventanas anteriores; buscadores, ciudades, países, dispositivos, edad, sexo, principales páginas de aterrizaje y frases de búsqueda; y todos los canales de tráfico. El renderizado convierte ese documento en HTML autocontenido con gráficos SVG en línea y lo imprime a PDF mediante Chrome, Edge o Chromium instalados localmente (SEOHEAD_CHROMEtiene prioridad en la búsqueda). La marca (nombre, colores, pila tipográfica, texto del logotipo) y las etiquetas en inglés o ruso son entradas; las filas de consultas de Search Console pueden añadirse como página opcional. La atribución por defecto es el último origen significativo (ym:s:lastSignTrafficSourcey sus dimensiones de motor y frase), que es lo que muestra la interfaz de Metrika; las dimensiones de último clic difieren de ella en unos pocos por ciento y siguen disponibles comoattribution=last_clickexplícito. Cada petición incluyeoffset=1, porque la API cuenta las filas desde 1. Los datos ausentes se mantienen visibles: cada bloque llevaok,unavailableoskippedcon un motivo; un cambio sin base de comparación esnully no cero; si falta el navegador, el HTML se genera pero el PDF se marca como omitido; y los archivos existentes enout_dirsolo se reemplazan conoverwrite=true.CambiadoFuncionaLos informes de Metrika empiezan en
offset=1: la Reporting API cuenta desde 1 y#707respondía con HTTP 400 a cada petición enviada con
#707 (incidencia en GitHub)offset=0(#707, #728, #729).
26 de septiembre de 2026
1 añadidoAñadidoFuncionaEvidencia
HEADING_SKIPpara saltos de nivel H1–H6 en el rastreo nativo#725Añade evidencia
#725 (incidencia en GitHub)HEADING_SKIPen el rastreo nativo para los saltos de nivel H1–H6 en la región de contenido nombrada. Se excluyen los encabezados de cabecera, pie, navegación, barra lateral y los ocultos explícitamente o en diálogos cerrados, para que la interfaz de la plantilla no genere una jerarquía falsa. Las ejecuciones solo de exportación de Screaming Frog marcan esta comprobación como no disponible.
23 de septiembre de 2026
1 cambiadoCambiadoFuncionaArchivos secretos privados en Windows y consentimiento de Search Console#708
Acepta archivos secretos privados en Windows, donde no existen los bits de permisos POSIX, y añade un script de consentimiento en el navegador que guarda una concesión de solo lectura para Search Console.
#708 (incidencia en GitHub)
13 de septiembre de 2026
2 añadido3 cambiado2 corregidoAñadidoFuncionaSoporte para SQLite nativo en Windows#705
Soporte para escritores SQLite nativos, histórico, reintentos, instantáneas, reanálisis y publicación de proyectos en Windows, con bloqueos de rango de bytes respaldados por el sistema operativo y comprobaciones portables de espacio libre. Se mantiene el vaciado de directorios POSIX; el vaciado de archivos en Windows y la publicación atómica siguen disponibles sin garantía de fsync de directorio POSIX. Los flujos portables se ejecutan en el CI de Windows y en un entorno Linux aislado.
#705 (incidencia en GitHub)CorregidoFuncionaCompatibilidad del escaneo HTML con versiones antiguas de Python#705
Mantiene el escaneo de HTML en texto plano compatible con versiones de Python que no tienen la opción de scripting más reciente de HTMLParser, incluida la distribución de Python 3.12 para Windows.
#705 (incidencia en GitHub)CorregidoFuncionaGuías de datos estructurados y Googlebot corregidas y citadas#704
Corrige y cita con fuentes las guías de Google sobre datos estructurados y Googlebot, incluidas la disponibilidad de FAQ/HowTo y las consecuencias de la política de datos estructurados.
#704 (incidencia en GitHub)CambiadoFuncionaDescubrimiento de sitemaps desde
robots.txt, con/sitemap.xmlcomo alternativa#703Descubre los sitemaps desde la raíz del sitio a través de
#703 (incidencia en GitHub)robots.txt, con/sitemap.xmlcomo alternativa, e informa de una expansión de sitemaps en la que todo ha fallado comook: false.CambiadoFuncionaReanudación del rastreo nativo tras cookies anónimas#702
Permite reanudar el rastreo nativo tras cookies anónimas establecidas por el servidor, y registra la sesión nueva sin conservar los valores de las cookies; los rastreos con credenciales o con perfil persistente siguen sin poder reanudarse.
#702 (incidencia en GitHub)CambiadoFunciona
--scanpara rutas de escaneo guardadas y--inputpara JSON en línea#701Estandariza las rutas de escaneo guardadas como
#701 (incidencia en GitHub)--scany el JSON en línea como--input; los usos heredados de--inputy--json-inputcon rutas de escaneo siguen funcionando durante una versión, con aviso.AñadidoFuncionaConfirmación explícita para conservar evidencia anónima no-store#700
Añade una confirmación explícita, desactivada por defecto, para conservar evidencia anónima acotada con
#700 (incidencia en GitHub)Cache-Control: no-store, mientras se siguen omitiendo los cuerpos con credenciales.
9 de septiembre de 2026
10 añadido9 cambiado2 corregidoAñadidoFuncionaVistas previas offline de prioridades y aplicación explícita de políticas#694
Añade vistas previas offline de prioridades del proyecto y aplicación explícita y versionada de políticas, usando los hechos de stack guardados. Conserva las decisiones del operador, un histórico atómico de políticas y las explicaciones de prioridad coincidentes en los informes para personas.
#694 (incidencia en GitHub)CorregidoFuncionaCorrige las guías de renderizado JavaScript, canonical, URL y
notranslate#692Corrige las recomendaciones sobre renderizado de JavaScript, canonical, higiene de URL y
#692 (incidencia en GitHub)notranslate, sin cambiar las comprobaciones en tiempo de ejecución ni las severidades.- CorregidoFuncionaLa fixture de documentación usa el origen loopback efímero#690 (incidencia en GitHub)
AñadidoFuncionaChecklist de proyecto portable con catálogo empaquetado#686
Añade cobertura portable de checklist de proyecto con un catálogo empaquetado derivado de las fuentes, plantillas personalizadas reutilizables, histórico de definiciones y de evidencias, escrituras concurrentes optimistas, revisión manual y de entregables explícita, y vistas offline de pendiente, obsoleto y bloqueado. Las comparten la CLI, el MCP y los informes humanos vinculados a proyectos.
#686 (incidencia en GitHub)AñadidoFuncionaResumen de estado de escaneo nativo de solo lectura#685
Añade un resumen de estado de escaneo nativo, de solo lectura, para las poblaciones de la frontera y los resultados HTTP confirmados.
#685 (incidencia en GitHub)AñadidoFuncionaEspacios de trabajo de proyecto locales y portables#678
Añade espacios de trabajo de proyecto locales y portables, con estados explícitos de checklist pendiente y de preparación.
#678 (incidencia en GitHub)AñadidoFuncionaRevisión de la guía de Google Search Central: 175 guías leídas y tres correcciones#677
Registra en el repositorio la revisión de la guía de Google Search Central: 175 guías leídas, sus etiquetas, exclusiones, fecha de la instantánea y las tres correcciones que produjo.
#677 (incidencia en GitHub)CambiadoFuncionaEn modo URL,
crawl-siteescribe un escaneo SQLite nativo a prueba de colisiones#676En modo URL,
#676 (incidencia en GitHub)crawl-siteescribe ahora por defecto un escaneo SQLite nativo a prueba de colisiones en el directorioscans/de quien llama.--out-dirsigue siendo la ruta heredada y explícita de directorio, mientras que la entrada en lista y la configuración de caché live/replay indican esa ruta en lugar de cambiar el modo de recogida en silencio.CambiadoFuncionaLas compilaciones limpias incrustan la procedencia validada del productor#675
Las compilaciones de distribución limpias incrustan ahora la procedencia validada del productor en los escaneos SQLite nativos cuando no hay un checkout del código fuente disponible.
#675 (incidencia en GitHub)CambiadoFuncionaSustituidas las afirmaciones sin soporte sobre 301 y 302 en la skill de auditoría#671
En la skill de auditoría incluida en el paquete, sustituye las afirmaciones sin soporte sobre pérdida de señal con 301 fijo y la ausencia categórica de autoridad de enlace con 302 por una guía basada en la intención permanente o temporal y en el destino canonical, citando Google Search Central. Las redirecciones temporales siguen siendo válidas para cambios temporales; un código de estado por sí solo no mide una pérdida de posicionamiento.
#671 (incidencia en GitHub)CambiadoFunciona
render-check --viewport mobileahora usa una única identidad de diagnóstico estable#670para smartphone en sus solicitudes brutas y de navegador. Hay un
#670 (incidencia en GitHub)--user-agentexplícito disponible en CLI y MCP, y cada comparación completa o parcial registra la identidad efectiva y el tamaño del viewport.AñadidoFuncionaAñade entradas
--scande solo lectura para el análisis de corpus de duplicados y#669boilerplate, con cobertura del cuerpo conservado y procedencia.
#669 (incidencia en GitHub)AñadidoFuncionaAñadido un catálogo generado de entradas de comandos y documentada la decisión sobre el#668
almacén del escaneo, la caché HTTP y el diario de ejecuciones.
#668 (incidencia en GitHub)CambiadoFuncionaLos informes de cliente en Markdown, CSV, XLSX, DOCX y de tareas ahora usan títulos de#660
hallazgo pensados para quien los lee…
Los informes para el cliente en Markdown, CSV, XLSX, DOCX y de tareas ahora usan títulos de hallazgo pensados para quien los lee, y la reproducción guardada como evidencia, en lugar de identificadores del registro o nombres de colectores. Los registros históricos sin evidencia suficiente lo indican de forma explícita, y los artefactos de auditoría en JSON no cambian.
#660 (incidencia en GitHub)AñadidoFuncionaAñade
project-factspara registrar los datos del stack tras crear el proyecto,#648opcionalmente desde una pasada…
Añade
#648 (incidencia en GitHub)project-factspara registrar los datos del stack del proyecto tras su creación, opcionalmente a partir de una única pasada explícita detech-detectque respete robots.txt. Las decisiones introducidas por el operador prevalecen sobre la evidencia detectada, y una detección no disponible o ambigua queda sin registrar, con su motivo.CambiadoFuncionaEmpieza el README por el controlador del proyecto y presenta Screaming Frog como segunda#648
pasada de contraste, no como estándar de paridad.
#648 (incidencia en GitHub)AñadidoFuncionaIncluye
examples/project-skeletoncon una lista de comprobación inicializada y sin#648resultados, para que
#648 (incidencia en GitHub)project statussobre él muestre recuentos de cobertura en lugar denot_initialized, y valida ese archivo contra el catálogo activo.AñadidoFuncionaAñade contratos para la preparación del proyecto, la evidencia de proveedores, el corpus#354
guardado, la extracción acotada, la evidencia de escaneo y el catálogo de workflows, con límites explícitos para la evidencia conservada y el progreso.
#354 (incidencia en GitHub)CambiadoFuncionaLos perfiles MCP y los wrappers de progreso que conservan metadatos requieren el SDK#354
opcional de MCP 1.29…
Los perfiles MCP y los wrappers de progreso que conservan metadatos requieren el SDK opcional de MCP en la versión 1.29 o posterior.
#354 (incidencia en GitHub)CambiadoFuncionaSimplificado el README en torno a los flujos de tarea → comando → artefacto, eliminados
los embebidos visuales obsoletos y los contadores de marketing, y conservados los enlaces a las referencias generadas de la superficie de interfaz activa.
CambiadoFuncionaAmplía el README con flujos prácticos de entrada a resultado, con las llamadas CLI/MCP
equivalentes y los límites precisos del corpus conservado y de los proveedores y el navegador.
8 de septiembre de 2026
8 cambiado2 corregidoCambiadoFuncionaReconcilia la documentación del artefacto SQLite con el cuerpo nativo entregado, el#666
historial y…
Reconcilia la documentación del artefacto SQLite con los contratos entregados de cuerpo nativo, historial y reanálisis sin conexión (#666). La tabla de campos de página tardía documentada ahora se contrasta con el mapeo del importador, de modo que una observación JSONL antigua sigue siendo SQL NULL y no se convierte en un valor limpio inventado.
#666 (incidencia en GitHub)CambiadoFuncionaLas auditorías nativas ahora señalan como omitidas las comprobaciones de meta keywords,#659
canonical secundario, versión HTTP y amphtml cuando no se recopilaron sus campos de origen.
#659 (incidencia en GitHub)CorregidoFuncionaDeja de leer como credencial del operador una cookie que el propio sitio estableció en el#656
carril de renderizado JavaScript, y avisa cuando una ejecución descarta los DOM renderizados (#656). Un navegador devuelve lo que la propia
#656 (incidencia en GitHub)Set-Cookiedel sitio le dio, así que en cuanto una página fijaba una cookie de sesión y después pedía un subrecurso del mismo origen (un script, una hoja de estilos, una imagen, la forma habitual de la web), el hook de solicitud del renderizador leíaCookie:de la red y guardaba el DOM serializado de esa página comoomitted/credentialed, en una ejecución conhttp.credential_headers = []. Cada renderizado crea su propio contexto de navegador, así que la pérdida es por página y no acumulativa: cada página que fija una cookie pierde su propio DOM, y la ejecución informa de sus páginas, enlaces y recuentos de escalado exactamente como si fuera completa. Ahoracredentials_usedde un documento renderizado procede solo de lo que la ejecución está configurada para enviar (http.credential_headerso un perfil de navegador persistente), que es lo quecrawl/sqlite_render.py::_policy_factsya calcula y entrega al renderizador; este construye su propio cliente de red sin credencial, así que la red no tenía nada que añadir. Un rastreo con una credencial configurada sigue omitiendo esos DOM bajocredentialed, sin cambios, y el valor de la cookie nunca se almacena.CambiadoFuncionaAhora se nombran los recuentos renderizados que una marca
partialno puede transmitir.#656
#656 (incidencia en GitHub)rendered_bodiesen un resultado decrawl-siteindica cuántos DOM renderizados se conservaron y el motivo de cada uno que no se conservó. La CLI lo imprime junto a la línea final, en lugar de dejarlo a un indicador de capacidad que dice «parcial» tanto por un DOM ausente como por todos. Una ejecución que no descartó nada no imprime nada extra. Los recuentos se leen de nuevo del artefacto de escaneo, de modo que un escaneo terminado sigue respondiendo a la misma pregunta después.CambiadoFuncionaRecoge
og:urlen un rastreo nativo, en lugar de informar de que falta en cada página#654(#654).
#654 (incidencia en GitHub)rules.check_ogincluyeog:urlentre losmissing_tagsde una página siempre que el campo sea falso, y la ruta nativa nunca leía esa etiqueta: no habíaog_urlenPageRecord, ni columnaog_urlenscan_v1.sql, niOG:URLen la proyección Internal:All que construyecrawl/evidence.py. La columna solo existía en el lado de Screaming Frog, dondenormalizesiempre había resueltoOG:URL, así que una exportación del sitio veía el valor real y un rastreo nativo del mismo sitio notificaba un defecto: un campo no medido presentado como medido, en cada página de cada rastreo nativo, fuera cual fuera el marcado. Ahora la etiqueta se lee donde se leen las otras tres (el parser ya la devolvía comoog:url), se guarda enpages.og_urlcomo columna anulable —anulable como todas las columnas añadidas después, para que un registro escrito antes de recogerla siga distinguiéndose de una página que no declara ninguna— y se proyecta comoOG:URL. Es el lado de recogida de la costura que #646 corrigió en el lado de lectura.tests/test_open_graph_seam.pygana un tercer sitio de prueba cuyas páginas tienen Open Graph pero noog:title, de modo que el hallazgo se dispara de verdad y su lista se puede leer: una página declaraog:urly no debe aparecer como que le falta, y la otra no lo declara y sí debe aparecer. La prueba que importa audita esas dos páginas dos veces, una desde el rastreo y otra desde una exportación Internal:All que describe las mismas dos páginas, y exige el mismo veredicto: #646 y #654 eran dos rutas que discrepaban sin ninguna prueba que las abarcara a ambas.CorregidoFuncionaDeja de leer como credencial del operador una cookie que definió el sitio, y avisa cuando#647
una ejecución descarta cuerpos (#647). Un rastreo comparte un único cliente HTTP, y ese cliente mantiene un cookie jar: en cuanto una respuesta traía
#647 (incidencia en GitHub)Set-Cookie, todas las solicitudes posteriores salían conCookie:y el escritor del corpus las clasificaba como descargas autenticadas. En un sitio público conhttp.credential_headers = []ycredentials_acknowledged = false, eso descartó 33 001 de 40 920 cuerpos de página, y la ejecución informó de sus páginas y enlaces exactamente como si estuviera completa. Todo lo calculado a partir del HTML almacenado en ese rastreo (detección de casi duplicados, profundidad y número de nodos del DOM, proporción de boilerplate, estructura de encabezados dentro del cuerpo, reanálisis sin conexión) abarcaba entonces 7 903 páginas, mientras que cada porcentaje a nivel de página del mismo informe abarcaba 40 920: dos poblaciones presentadas como una sola. Una captura es credentialed cuando la ejecución estaba configurada para enviar una cabecera de credencial para ese host, que es la única forma de que una cabecera sensible llegue a una solicitud que construye el rastreador (http.headerslo rechaza la validación de configuración). Un rastreo con una credencial configurada sigue omitiendo esos cuerpos bajocredentialed, sin cambios.CambiadoFuncionaLos recuentos que una marca
partialno puede transmitir ahora se nombran.#647
#647 (incidencia en GitHub)html_bodiesen un resultado decrawl-siteindica cuántos cuerpos HTML de página descargados se conservaron y el motivo de cada uno que no se conservó. La CLI lo imprime junto a la línea final, en lugar de dejarlo a un indicador de capacidad que dice «parcial» tanto por un cuerpo ausente como por cuatro quintas partes de ellos. Una ejecución que no descartó nada no imprime nada extra. Las listas de cabeceras de solicitud y respuesta redactadas conservan ahora los nombres de las cabeceras que la redacción eliminó, bajox-seohead-redacted-headersy nunca sus valores: dos respuestas cuyos cuerpos se trataron de forma distinta registraban listas de cabeceras idénticas byte a byte, así que quien leía el artefacto no podía saber por qué faltaba un cuerpo.CambiadoFuncionaMueve las entradas del changelog fuera de
CHANGELOG.mdy a un archivo por cambio bajo…#638Mueve las entradas del changelog de
#638 (incidencia en GitHub)CHANGELOG.mda un archivo por cambio dentro dechangelog.d/, de modo que un pull request ya no entre en conflicto con todos los demás que se integraron antes (#638). Cada rama añadía su entrada al principio de## Unreleased, lo que convertía esa única línea en el punto de contención del archivo: nueve resoluciones manuales en ocho pull requests a lo largo de dos sesiones, cada una un nuevo push y una nueva ejecución de CI, y la resolución era siempre «conserva nuestro bloque y luego el suyo». Un conflicto cuya respuesta nunca varía no aporta información, y es una ocasión para perder un párrafo mientras se piensa en otra cosa. La corrección de.gitattributesque proponía la incidencia (CHANGELOG.md merge=union) se midió y se descartó antes: union fusiona línea a línea, así que cuando dos entradas contienen una línea idéntica (basta una línea en blanco dentro de una entrada), conserva una copia e informa de éxito, borrando en silencio la línea de la otra entrada sin conflicto y sin que nadie tenga motivo para revisarlo. Una primera prueba con líneas deliberadamente distintas se fusionó limpiamente y ocultó ese problema. Cambiar un conflicto ruidoso por pérdida silenciosa de datos es estrictamente peor que el conflicto, así que se publicó la solución estructural.CambiadoFuncionaUn fragmento se nombra según la incidencia que cierra (
changelog.d/638.md), la clave#638que es única por rama por construcción: un pull request que cierra dos incidencias escribe dos fragmentos, uno por incidencia, y un cambio que no cierra ninguna escribe
#638 (incidencia en GitHub)no-issue-<slug>.md. Un fragmento contiene la entrada tal como debe aparecer en el changelog (uno o más puntos de primer nivel con sus líneas de continuación, sin front matter ni envoltorio), de modo que las entradas en prosa de varios párrafos que este archivo conserva pasan de ida y vuelta byte a byte en lugar de reformatearse en líneas sueltas.python scripts/build_changelog.pylos integra en## Unreleaseden el momento de la publicación, ordenados por número de incidencia y no por el orden que devuelva el sistema de archivos, y--pruneelimina los fragmentos que integró. El ensamblado reemplaza toda la región comprendida entre dos comentarios marcadores en lugar de insertar en ella, así que ejecutarlo dos veces produce el mismo archivo en ambas ocasiones, tanto si los fragmentos se eliminaron entre medias como si no.CHANGELOG.mden sí no se regenera en cada pull request, deliberadamente: una puerta que lo mantuviera sincronizado continuamente volvería a poner ambas ramas en el mismo archivo y reconstruiría el conflicto que esto elimina.CambiadoFuncionaLas puertas de documentación que leían
CHANGELOG.mderan el riesgo, porque una puerta#638que deja de comprobar en silencio es peor que los conflictos…
Las puertas de documentación que leían
#638 (incidencia en GitHub)CHANGELOG.mderan el riesgo, porque una puerta que deja de comprobar algo en silencio es peor que los conflictos. Ambas se encontraron y ahora cubren los fragmentos:tests/test_docs_drift.pyteníaCHANGELOG.mdenPUBLIC_MARKDOWN, así que la puerta solo en inglés, la de «referencias solo a comandos existentes» y la de recuentos obsoletos también leen ahorachangelog.d/*.md, y las dos puertas de deriva de recuentos omiten un fragmento por la misma razón que omiten el changelog: una entrada registra lo que era cierto cuando se escribió.tests/test_doc_counts.pyexcluye deliberadamente el changelog de su escaneo de recuentos en vivo, y su lista de archivos nunca llega achangelog.d/, que es la misma respuesta por el mismo motivo;tests/test_doc_commands.py,tests/test_docs_commands_execute.pyytests/test_examples_gate.pynunca leen el changelog. Un nuevotests/test_changelog_fragments.pyfija cada una de esas respuestas, junto con el nombrado de fragmentos, el orden determinista, el ensamblado idempotente y el hecho de que dos ramas concurrentes simuladas que añaden cada una un fragmento se fusionan sin conflicto.
Antes (sin fecha registrada)
23 añadido30 cambiado17 corregidoCorregidoFuncionaSigue identificando una página cuyo sitio envía una cabecera
Set-Cookiesin valor(#651).
Una cabecera sin ningún par
name=value(Set-Cookie: Secure; HttpOnly, queemall.byenvía junto a dos cookies bien formadas) se convierte enCookie(name='Secure', value=None)en el jar, yhttpx.Cookies.__getitem__lanzaKeyErrorpara ella. Por esodict(resp.cookies)fallaba con un nombre que el propio iterador del mapeo había producido:tech-detectterminaba con código 1 y un simpleerror: 'Secure'sin JSON en stdout, para una página que se había descargado con éxito; el MCPseo_tech_detectpropagaba elKeyErrora quien lo llamaba, ysite-auditvolvía en silencio sin su sección de tecnologías. Ahoradetect_techrecorre el jar de cookies. Un nombre sin valor se conserva con valor vacío en lugar de descartarlo, porque varias huellas (BITRIX_SM_GUEST_ID,craft_session,wfvt_) coinciden solo por el nombre de la cookie, y descartar la entrada perdería esa señal; pero nunca se normaliza en silencio como una cookie corriente: los nombres se informan enmalformed_cookiesy se citan en un hallazgo, de modo que una cabecera que el sitio envió rota sigue siendo un hecho sobre el sitio. Una respuesta con solo cookies bien formadas no cambia y devuelve una lista vacía.CambiadoFunciona
render-checkvuelve a medir sitios comprimidos en lugar de darlos por rotos (#650).La ruta de renderizado fijada leía el origen con el stream sin decodificar de httpx y entregaba esos bytes a Playwright junto con el
content-encodingdel origen.route.fulfillnunca aplica una codificación de contenido al cuerpo que recibe, así que Chromium interpretaba gzip comotext/htmly construía un DOM a partir del flujo comprimido: sin título, sin h1, sin canonical, sin enlaces, y un tamaño renderizado igual a la transferencia. Cada sitio que comprime su HTML (casi todos) salía comook: false, reason: incomplete_render, y el mensaje culpaba al renderizado y sugería--wait domcontentloadedo un--timeoutmás largo, aunque el renderizado había terminado perfectamente.seohead.techinformaba 22 435 bytes renderizados frente a 121 793 brutos; ahora informa 123 048 con el título real y 31 enlaces. La ruta lee ahora la entidad decodificada, eliminacontent-encodingde lo que reenvía (content-lengthya se eliminaba como hop-by-hop, así que Playwright declara la longitud del cuerpo que realmente recibió) y pide al origen solo las codificaciones que este cliente sabe decodificar, en lugar de reenviar la invitación de Chromium abryzstd. Si una codificación llega sin decodificar de todos modos, la solicitud se aborta y nombra esa codificación, porque dejarla pasar reproduciría el error en silencio. El límite de bytes cuenta ahora bytes decodificados, que es el cuerpo que ve el renderizador: antes, una bomba de compresión pasaba el límite comprimida.CambiadoFuncionaLee Open Graph de un rastreo nativo por la clave que el parser realmente escribe (#646).
parse_htmlguarda cada etiqueta bajo su nombre completo de propiedad ({"og:title": ...}, como dice su propio docstring), ycrawl/collect.pypedía al mismo diccionario"title","description"e"image".dict.getdevolvíaNonesiempre, así queog_title,og_descriptionyog_imagequedaban vacíos en cada página de cada rastreo nativo que se había ejecutado: 0 de 40 920 páginas tenían alguno en la ejecución donde apareció el problema, en un sitio cuyas páginas sí publican Open Graph. Es la regla central del repositorio invertida: un campo no medido leído como medido, y el error se propagó, porquecrawl/evidence.pyproyecta esas columnas enOG:Title,OG:DescriptionyOG:Imagedel marco Internal:All, así que una comprobación veía vacío en un rastreo nativo y el valor real en una exportación de Screaming Frog del mismo sitio. La honestidad decheck_ogocultó el daño en lugar de mostrarlo: como ninguna columna OG se rellenaba en ningún sitio, la comprobación se omitía, así que un sitio con Open Graph se auditaba igual que uno sin él. El parser no cambia; solo se movió el lado de lectura. Un nuevotests/test_open_graph_seam.pyrastrea dos sitios de prueba en loopback y sigue el valor desde el parser hastapages.jsonl, luego a la tablapagesdel artefacto de escaneo y después a las columnas del marcoOG:*; rastrea un segundo sitio sin Open Graph para distinguir «vacío porque no existe» de «vacío porque no se leyó», y fija en el mismo archivo la forma de clave del parser. El fallo era que dos módulos correctos no coincidían en el nombre de una clave, sin ninguna prueba que abarcara a ambos.CambiadoFuncionaResponde a «¿está bien enlazado este sitio y dónde está mal enlazado?», tomando el
registro de 157 a 161 comprobaciones y añadiendo una skill
internal-linking(#634). Las piezas existían (cada enlace con su posición, ancla y marca nofollow en la tablalinks,ORPHAN_PAGE,INLINK_BOILERPLATE_ONLY,LOW_LINK_SCORE), y nada las convertía en una respuesta sobre el grafo. Una auditoría de 40 920 páginas llevaba durante horas el titular equivocado por esa razón: el 66 % del sitemap se informaba como inalcanzable por enlaces internos, una cifra que resultaba de restar el número de URL de un rastreo al del sitemap, lo que mide «el rastreador no llegó hasta allí». Recorrer los 5 252 235 enlaces del propio artefacto desde la página de inicio situaba la alcanzabilidad en el 91,9 %. El defecto real era la profundidad: 23 742 páginas (el 58 % del sitio) estaban a más de diez clics de la página de inicio, y la más profunda estaba a 3 005, porque el archivo es una lista enlazada de enlaces «siguiente entrada» en lugar de un árbol. La profundidad de clic es ahora el titular que imprime la auditoría.summary.internal_linkingcontiene el histograma, el máximo, la división alcanzable/inalcanzable, los enlaces internos por posición en la página y cuántos enlaces repiten otro, yaudit.mdlo muestra junto al resumen de salud. El recorrido empieza en la URL desde la que realmente arrancó el rastreo, nunca enpages.crawl_depth: esa columna registra dónde llegó el rastreador a una URL por casualidad, y un rastreo sembrado desde el sitemap registra 0 en la mayor parte del sitio, así que un recorrido sembrado desde ella describiría otro lugar. Si no se registró ninguna URL de inicio y más de una página reclama profundidad 0, la medición se niega a ejecutarse y dice cuál.CambiadoFuncionaCuatro comprobaciones leen esos números.
DEEP_CLICK_DEPTHse dispara en una página indexable cuya ruta más corta desde la URL de inicio superathresholds.click_depth_max(por defecto 10, y cada hallazgo nombra el número que usó).DUPLICATE_INTERNAL_LINKse dispara en una página que escribe el mismo destino y ancla más de una vez: en el sitio anterior, 509 744 de 1 134 307 enlaces (el 44,9 %) eran repeticiones, y se trataba de una misma cabecera de sitio emitida dos veces, con la segunda copia eliminada por JavaScript, un defecto de plantilla que había requerido un script escrito a mano para encontrarlo.LINK_INSIDE_HEADINGyIMAGE_LINK_WITHOUT_TEXTnecesitan lo que la región de página de un enlace no puede contener (la cadena de ancestros del propio ancla y su contenido), así que un rastreo nativo registra ahora unlink_placement_jsonpequeño y acotado por página junto al esquema de encabezados, y ambas comprobaciones se omiten por nombre en una exportación de Screaming Frog en lugar de pasar limpias sobre nada.CambiadoFuncionaLas reglas de honestidad que el resto del analizador mantiene se aplican en todo el
conjunto.
Un enlace sin posición registrada se cuenta como
unclassifiedy nunca se suma acontent:link_position.classifyviene desactivado por defecto, lo que deja esa marca en cada enlace, y una ejecución en ese estado debe leerse como «nadie lo revisó» y no como un sitio cuyos enlaces son todos texto de cuerpo. Una posición ausente de la distribución se informa como «ningún enlace clasificado aquí», no como una región que el sitio no tiene: las reglas se prueban en orden y un menú dentro de<header>coincide primero connav. Un rastreo parcial retira el veredicto de profundidad de clic, se haya disparado o no, porque una frontera nunca descargada puede contener la ruta más corta, y una comprobación que no encuentra nada en silencio se leería como «todas las páginas están dentro del umbral».CorregidoFuncionaDeja de informar como limpia una comprobación condicionada por requisito que nunca se
evaluó (#635).
H2_MISSINGsolo se dispara cuando una configuración establecerequirements.require_h2, y el valor por defecto es false, así que en una ejecución normal su rama es inalcanzable. Eso no dejaba rastro: la cobertura lo contaba entre las comprobaciones silenciosas (el cubo que significa «se ejecutó sobre todas las páginas y no encontró nada»), y al lector se le decía que el sitio había superado una comprobación que nadie ejecutó. En la auditoría que lo sacó a la luz, el 61 % de las páginas del sitio no tenía ningún H2 y 5 066 de ellas superaban las 800 palabras, así que la comprobación se habría disparado miles de veces. Ahora se declara omitida por nombre, con un motivo que nombra el ajuste que la desactivó, de modo que la respuesta es «no evaluada, y así se evalúa» en lugar de silencio.require_canonicaltiene la misma forma y recibe el mismo tratamiento; su valor por defecto es true, así que todavía no producía una lectura errónea, y ahora no puede empezar a hacerlo.CorregidoFuncionaCorrige el encabezado del backlog de tareas que mostraba «Audit Tasks — None» en
cualquier auditoría cuya ejecución…
render_tasks_mdconstruía el encabezado consrc.get("project", "site"), pero"project"siempre es una clave presente en el bloquesourcedel backlog: se fija en el momento de la construcción desderun.get("project"), así que una ejecución sin proyecto guarda el valorNoneahí en lugar de dejar la clave ausente, y el valor por defecto dedict.getsolo se aplica a una clave que falta, nunca a una que contieneNone. Un rastreo nativo y un reanálisis dejanprojectsin definir, así que cada backlog construido a partir de cualquiera de ellos recibía como encabezado la palabra literal «None». Ahora el encabezado usaor, que sí captura unNonealmacenado, y recurre astart_urlo asourcedel sitio antes de rendirse: el mismo orden queseohead.reports.facts.crawl_domainya usaba para resolver el nombre de un sitio a partir de su bloquerun, ahora exportado y reutilizado aquí en lugar de reinventado, de modo que un backlog construido desde una auditoría sin proyecto nombra el sitio real en lugar de la palabra «site».seohead.reports._normalize_sf_audittenía la misma forma latente una línea más arriba (run.get("project") or "", enreports/__init__.py): ya estaba protegido contra unNonealmacenado, pero su alternativa era un dominio vacío en lugar de la URL que la ejecución también conoce, así que el encabezado «SEO Audit: » de los formatos docx y md quedaba en blanco en las mismas situaciones. Ahora recurre a la misma resolución decrawl_domain, en lugar de quedarse vacío.CambiadoFuncionaLee el esquema de encabezados como secuencia y como mapa de la página, tomando el
registro de 155 a 157 comprobaciones (#632).
Las ocho comprobaciones de encabezados existentes juzgan los encabezados como conjunto: pueden afirmar que una página tiene un H1 y cuatro H2, y nada más. Así, una página cuyo orden en el DOM es
H2, H2, ..., H1, H2cumplía todas, y también una página cuyos H2 eran todos etiquetas de menú en su cabecera (encontrada en un sitio real como una plantilla de artículo con dieciocho encabezados antes de su propio H1). Lo que faltaba era la evidencia, no la regla:pagesguardabah1,h1_2yh2, tres cadenas sin orden ni lugar. Un rastreo nativo registra ahora el esquema completoh1-h6en orden DOM, cada encabezado con su nivel, texto y región de página, en una nueva columna anulableheading_outline_json, yHEADING_BEFORE_H1yHEADING_IN_PAGE_CHROMElo leen. La región reutiliza la taxonomía que ya usa la clasificación de enlaces (nav,header,sidebar,footer,content,other), de modo que «en la cabecera» significa lo mismo para un encabezado que para un enlace. Un encabezado que ninguna regla de posición reconoce se sitúa frente al área de contenido solo cuando el documento nombra una: un<main>, un[role=main], un<article>o un selector configurado. Cuando la raíz de contenido recurre a todo el<body>, llamar «contenido» a un encabezado significaría solo «en algún lugar de la página», así que la región se registra como no medida y la página aparece entre las comprobaciones omitidas de la ejecución con ese motivo, en lugar de pasar como limpia o marcarse como defecto. El orden no necesita región, así queHEADING_BEFORE_H1sigue respondiendo para esas páginas. Una exportación de Screaming Frog no trae ningún esquema, y ambas comprobaciones se omiten allí por nombre.CorregidoFuncionaConserva una recopilación terminada cuando la auditoría que la sigue falla (#627).
Un rastreo nativo de un sitio en vivo pasó veinte minutos recopilando 600 páginas en un artefacto
--scan-outy luego imprimióerror: 'rel_next_2'(elstr()de unKeyErrores solo la clave y nada más). Sin fase, sin traceback y sin indicio de que cada página recopilada estaba completa y se podía reanalizar en el archivo. La recopilación confirma sus filas y se cierra antes de que empiece la auditoría, así que cualquier excepción posterior a ese punto es un fallo del analizador y nunca del rastreo. Ahora una excepción inesperada en esa fase se nombra por fase, incluye el tipo de la excepción además de su mensaje y señala el artefacto conservado y el comando que lo reanaliza, igual que ya hacía la ruta de auditoría demasiado grande. La ejecución informaaudit_available: falsecon ese motivo en lugar de terminar por la excepción, ycrawl-sitesale con código 2 en ese caso: la misma tercera respuesta que ya usa la contradicción del log-scan, porque 0 se leería como «la auditoría se ejecutó y encontró esto» y 1 como «el comando no produjo nada», y ninguna de las dos cosas es cierta para un rastreo cuya evidencia sobrevivió. ElKeyErroren sí no se reprodujo: el mismo comando contra el mismo sitio en la rama principal actual se completó, así que esto cambia qué ocurre cuando falla una auditoría, no lo que causó este fallo concreto.CorregidoFuncionaDeja de perder la auditoría de un rastreo completado por un presupuesto fijo de
inspección de 30 segundos al reabrirlo (#631).
NativeScan.open()lee la cabecera de un escaneo nativo a través deinspect(), que además ejecutaPRAGMA quick_checkyPRAGMA foreign_key_checksobre toda la base de datos: una comprobación de seguridad real, pero cuyo coste crece con el artefacto mientras el presupuesto no. Un rastreo de 3,5 horas y 40 920 páginas terminó de recopilar todo lo que se propuso y luego no produjo ninguna auditoría, porque reabrir el artefacto resultante de 1 GB necesitaba unos 48 segundos de validación frente a un presupuesto fijado en 30. Peor aún, el fallo no daba ninguna pista de que el problema era el presupuesto: el aborto por tiempo llega desde SQLite como un simplesqlite3.OperationalError("interrupted"), que se envolvía tal cual encannot inspect native scan: interrupted, indistinguible de un archivo realmente corrupto. Se corrigen las dos cosas. El presupuesto por defecto se deriva ahora del tamaño del artefacto (un mínimo de 30 segundos para archivos pequeños, más una holgada asignación por byte, bastante por debajo de la velocidad de validación medida de unos 22 MB/s, porque esto es un techo frente a una lectura colgada y no un objetivo de rendimiento); untimeout_secondsexplícito de quien llama sigue prevaleciendo. Y un aborto por tiempo lanza ahora unScanErrorque nombra el presupuesto, el tiempo transcurrido y el tamaño del artefacto, de modo que quien opera puede distinguir un archivo grande y lento de uno corrupto, en lugar de leer «interrupted» como un error suyo.AñadidoFuncionaAñade
crawl-site --resume <scan.sqlite>(#619).NativeScan.resume_snapshot(), la tablaresume_statey el escritor que la rellena existían desde que se diseñó el artefacto de escaneo, ycrawl_to_scanya continuaba un archivo existente, pero solo para quien llamaba reproduciendo byte a byte los ajustes efectivos originales, y ninguna interfaz lo ofrecía. Apuntar--scan-outa un artefacto interrumpido con cualquier flag cambiado se rechazaba como desajuste de configuración, así que en la práctica un rastreo interrumpido (6 516 de 34 635 páginas, sobre el sitio de otra persona) tenía que empezar desde cero.--resumerecibe solo el artefacto y nada más: la URL de inicio y la configuración efectiva completa se leen del archivo, porque son aquello con lo que se construyó la frontera almacenada, y cualquier otro flag que module el rastreo y se pase junto con él se rechaza en lugar de aplicarse. Un escaneo escrito por otra versión del programa, registrado para otra URL de inicio, ya terminado, derivado de un reanálisis o rastreado con cabeceras de credencial que solo puede almacenar redactadas se rechaza por nombre a partir del propio archivo, antes de despachar una sola solicitud.crawl-siteimprime ahora también al salir una línea en stderr que indica si el rastreo terminó o se detuvo antes, por qué, y cómo continuarlo; salvo tras un presupuesto de URL o de duración, que un reanudado también lee y por tanto no puede pasar, caso en que la línea lo dice en lugar de ofrecer una operación sin efecto.run.crawl_resumedsigue siendo el registro duradero: un rastreo reanudado del sitio de prueba sin conexión descarga cada URL exactamente una vez entre ambos procesos y produce una auditoría idéntica a la de un rastreo sin interrupciones en todos los campos salvo ese.CorregidoFuncionaDeja de dar por limpia una página sin renderizar en
render-check, y deja de descartarla evidencia del HTML bruto con un renderizado fallido (#642). Dos consecuencias de la guarda de #623, ambas en
render.py. Primera: una renderización que agotó el tiempo en su hito de carga recurre a leer el DOM endomcontentloaded, lo que es sólido en sí mismo, pero cuando ningún script se había ejecutado para entonces, el DOM renderizado era igual al HTML bruto, el comparador no encontraba nada y la ejecución informabaok: True,js_dependent: Falsey el único hallazgo «Raw HTML and rendered DOM are materially equivalent; JavaScript rendering does not determine SEO-visible content», con gravedad de aviso, sobre una página que nadie había renderizado.wait_reachedregistraba la verdad, pero la auditoría de sitio solo transporta al informe el texto de los hallazgos, así que la verdad nunca llegaba. Ahora una ejecución que recurrió a un hito anterior lo dice en la propia lista de hallazgos, retiene la confirmación de que todo está bien y devuelvejs_dependent: None(esta ejecución no lo sabe) en lugar deFalse. Esto ocurría con el valor por defecto--wait load, no solo connetworkidlepedido de forma explícita. Segunda: la guarda devolvía su única declaración «la comparación no está disponible» antes de llegar a la rama de cáscara vacía, y el retorno temprano derender_checkomitía por completo la claveempty_shell. Así, un punto de montaje vacío de una aplicación de página única, quedetect_empty_shell()lee de la respuesta bruta del servidor y que no necesita navegador alguno, se descartaba junto con la renderización fallida. Como la cáscara de una SPA es justamente la página cuya renderización agota el tiempo, el hallazgo se perdía precisamente donde más importaba. Un hallazgo derivado de la mitad bruta sobrevive ahora a una renderización no terminada; solo se suprimen los hallazgos derivados de la mitad renderizada. En un rastreo, una sonda de renderizado que no llegó a ningún veredicto pasa ahora apatterns_unprobedcon su motivo (el canal de #626), en lugar de contar como un patrón medido y considerado sin necesidad de renderizado.CambiadoFuncionaInforma de un robots.txt ilegible como un hecho sobre el sitio, no como error interno
(#629).
EMPTY_ROBOTS(el sustituto que_fetch_robotsdevuelve en cada ruta donde no se pudo leer robots.txt) seguía con la forma de robots ya parseado de antes de que el parser incorporara grupos y sitemaps. La ruta de éxito devuelve la forma deparse_robots, y es la única forma que acepta el contextorobots_summarydel artefacto de escaneo, así que en modo--scan-outun rastreo se abortaba connative parsed robots summary is invalidsiempre que robots.txt era inalcanzable, respondía 429 o 5xx, redirigía fuera del host, entraba en un bucle, superaba el límite de saltos o devolvía un cuerpo que no eratext/plain. También abortaba si era un 404 simple, que no es un error sino el caso RFC 9309 de «sin restricciones» y el más frecuente de los siete. Así se perdían ambos resultados documentados tras una sola línea: un robots.txt ausente ahora permite rastrear sin restricciones de nuevo, y uno no disponible detiene la ejecución con una nota que indica cuál de las seis formas de fallo se produjo. El modo de rastreo en directorio heredado nunca lo notó, porque nada lee las claves antiguas. Lo encontramos en un sitio real cuyo robots.txt redirige con 302 a un endpoint de sincronización de cookies para cualquier user agent que no reconozca.CorregidoFuncionaCorrige que
escalate()cuente una sonda de renderizado fallida como «este patrón nonecesita renderizado» (#626). Para cada patrón de plantilla, toma una URL de muestra y decide si ese patrón necesita una descarga más completa con JavaScript renderizado, pero cuando todas las muestras de un patrón fallaban al sondear (un fallo al lanzar el navegador, un agotamiento de tiempo o un renderizado incompleto, los modos de fallo habituales de un rastreo real), el
for/elseseguía registrando el patrón como sondeado, y acababa ni escalado ni en la lista de patrones que la ejecución no pudo evaluar. Eso invertía la regla central del proyecto: la evidencia ausente o no medida nunca debe leerse como limpia. Un patrón del que no se había aprendido nada se rastreaba como estático en silencio y se informaba igual que uno medido de verdad y considerado sin necesidad de renderizado.EscalationResultinforma ahora de ese patrón enpatterns_unprobed, junto a los patrones cortados por plazo que ya se seguían allí, y registra el motivo del fallo de la sonda en el nuevopatterns_unprobed_reasons, de modo que un informe pueda decir «este patrón no fue evaluado» en lugar de dar a entender que sí. Un patrón con al menos una sonda exitosa no cambia: esto solo altera lo que ocurre cuando todas las sondas de un patrón devuelvenok: False.CorregidoFuncionaDeja de informar de un renderizado sin terminar como defecto del sitio en
render-check(#623).
Cuando la renderización no se completó, la instantánea renderizada llegaba sin título, sin
h1, sin canonical, con cero enlaces y una quinta parte de los bytes de la respuesta bruta, y el comparador leía esa vacuidad como evidencia sobre el sitio: emitía «el título cambia después de JavaScript» sobre un título que la renderización nunca leyó, y «el canonical lo inyecta JavaScript» sobre un canonical que nunca vio. En una auditoría real eso fueron cuatro falsos hallazgos seguidos, cada uno del tipo que lleva a un desarrollador a buscar un error de JavaScript que no existe. Ahora el par se evalúa antes de compararlo: cuando la respuesta bruta contiene puntos de referencia y el documento renderizado no contiene ninguno de ellos, con un tamaño que es solo una fracción del bruto, la comprobación devuelveok: falseconreason: "incomplete_render", un motivo con nombre que incluye ambos recuentos de bytes, y ambas instantáneas para inspección: sin hallazgos y conjs_dependent: nullen lugar defalse, porque la ejecución no lo sabe.site-auditlo registra ensummary.tools_failed, donde debe ir una comprobación no medida. La detección es deliberadamente estrecha: un solo punto de referencia que sobreviva, o un documento renderizado de al menos la mitad del tamaño de la respuesta bruta, se compara como antes, y una página sin título y sin enlaces en ninguno de los dos lados se mide y simplemente está vacía, no se da por no medida. Un título que un script reescribe de verdad sigue disparando su hallazgo. La estrategia de espera también ayuda con la causa habitual: un sitio cuyos scripts de analítica, chat o publicidad con sondeo largo nunca alcanzan el estado de red inactiva agotaba el tiempo de toda la comprobación bajo--wait networkidle; ahora recurre a leer el DOM endomcontentloadedsin una segunda navegación, conwait_reachedregistrando de qué hito procede realmente la instantánea, más una pausa breve para los scripts diferidos. Una página cuyo DOMContentLoaded nunca se disparó sigue siendo un fallo de renderizado, no uno incompleto.CambiadoFuncionaDa a
crawl-siteuna línea de progreso en vivo (#619, mitad de progreso).Un rastreo nativo imprimía su tasa de solicitudes efectiva y después no mostraba nada hasta terminar; en un sitio de 34 000 páginas, la única forma de saber que seguía trabajando era mirar cómo crecía el archivo de escaneo con
ls -la. Ahora la línea se actualiza en su lugar en una TTY, con las páginas descargadas, las URL conocidas hasta el momento, su porcentaje respecto a ese conjunto, la tasa actual de solicitudes en una ventana móvil, el tiempo transcurrido y el tamaño del artefacto de escaneo cuando--scan-outlo está escribiendo. Lo que deliberadamente no hace es sugerir un total que no puede conocer: un rastreador descubre su propia carga de trabajo, así que el denominador esfetched + queuedlimitado por el presupuesto de URL, se etiqueta comoknowny no comototal, y una línea de cabecera impresa una sola vez indica que la frontera sigue creciendo y que el porcentaje no es una estimación de cuándo terminará la ejecución. Una tasa no medible se muestra comorate n/a, nunca como0.0 req/s. Ambos números vienen de las propias estructuras del rastreo (en un escaneo SQLite, de la misma consultaresume_snapshotpor la que se guía el bucle de recopilación), de modo que lo que se ve en pantalla es lo que el artefacto contiene en ese instante y no un recuento paralelo que pueda desviarse. Una salida no TTY (una tubería, un archivo de registro, CI) recibe una línea sencilla cada 30 segundos en lugar de redibujos con retorno de carro, y un nuevo-q/--quietsilencia tanto la línea de progreso como la línea inicial de tasa, dejando intacto el resultado JSON en stdout.CambiadoFuncionaCierra las tres filas de paginación que #385 dejó abiertas, y lleva el registro de 152 a
155 comprobaciones…
PAGINATION_MULTIPLEyPAGINATION_URL_NOT_IN_ANCHORinforman de una página que declara dos sucesores distintos, o cuya URL declarada no aparece también como ancla en la misma página. Los sucesores se comparan tras normalizar la URL, la misma identidad que usa la mitad de ancla, de modo que/blog/page/2y/blog/page/2/procedentes de dos plugins son un único sucesor escrito de dos formas, no una serie ambigua.PAGINATION_URL_NOT_IN_ANCHORnecesita el inventario completo de enlaces de una página y lee para ello la exportación All Inlinks.PAGINATION_MULTIPLEno lo necesita y ahora lee primero las columnas de ocurrencia, más ligeras,Internal:Allconrel="next" 2/rel="prev" 2, del mismo modo queCANONICAL_MULTIPLEya responde a partir deCanonical Link Element 2; All Inlinks solo es una alternativa para un perfil cuyoInternal:Allse escribió sin esas columnas.PAGINATION_SEQUENCE_ERRORinforma de una ruptura en una secuencia de números de página que la serie sigue en otro caso, según la propia advertencia de la incidencia: una serie puede empezar en un número distinto de uno, un salto regular no es una ruptura, y una serie cuyas URL no indican número de página se declara no evaluada en lugar de juzgarla contra una numeración que habría que inventar. Cada serie que queda sin juzgar se nombra entre las comprobaciones omitidas de la ejecución, con el motivo que es cierto para *esa* serie: un salto regular, un ciclo, una serie demasiado corta para contener una secuencia y un número de página ilegible son cuatro afirmaciones distintas, y tres de ellas describen series cuyas URL indican todas su número. El recuento es por serie, no por ejecución, de modo que la forma habitual de WordPress (la página uno en/blog/sin número y el resto en/blog/page/N/) no puede desaparecer tras una única serie juzgable en otro punto del mismo rastreo.AñadidoFuncionaAñade una puerta de cobertura de veredictos (#98):
test_check_producer_gate.pydemostróque cada…
Añade una puerta de cobertura de veredictos (#98):
test_check_producer_gate.pydemostraba que cada ID de comprobación está registrado y que cada funcióncheck_*se despacha, pero no decía nada sobre si la conclusión de una comprobación se había probado alguna vez como verdadera frente a un marcado que de verdad tiene el defecto, ni sobre si se mantiene en silencio ante un marcado que no lo tiene. Esa es exactamente la brecha que dejó pasar #94, #95 y #96 a través de todas las pruebas existentes mientras seguían disparándose mal en sitios reales.test_check_verdict_coverage.pyrecorretests/de forma estructural (AST, no una lista fija de llamadas) buscando las dos mitades por comprobación, y hace fallar la compilación para cualquier comprobación recién añadida al registro sin una prueba en ambos sentidos ni una exención con nombre y motivo. De las 152 comprobaciones del registro, 88 ya tenían prueba en ambos sentidos; un nuevotest_check_verdict_gaps.pycierra otras 22 de las brechas baratas de probar que detectó el escaneo (longitud y duplicación de title y description, duplicación de H1, presencia de H2, higiene de URL, comprobaciones de directivas y marcado, códigos de respuesta, y las dos comprobaciones de exportación con filtro nativo). Las 64 restantes quedan nombradas, no ocultas, en el ratchetKNOWN_UNCOVEREDde la puerta: hay que reducir esa lista a medida que llega la cobertura, y nunca debe crecer para admitir una comprobación añadida después de que existiera esta puerta.CorregidoFuncionaCorrige un defecto en la selección de grupos de robots.txt que permitía que un valor
User-agentvacío anulara la política por defecto de un sitio (#566). Una líneaUser-agent:vacía, o una cuyo nombre de bot se tragaba un comentario en línea (User-agent: # old bot rule), se parseaba como un token vacío._rules_fortrataba ese token como cualquier otro nombre literal: es un prefijo de longitud cero de todos los agentes, así que coincidía con todos, y como contaba como coincidencia *con nombre*, superaba al grupo realUser-agent: *del archivo para cada rastreador que el archivo no menciona. Un robots.txt cuya única regla sustantiva eraUser-agent: * / Disallow: /figuraba, por tanto, como totalmente rastreable, tanto en el informe de acceso de bots de IA como en el propio control de descargas del rastreador en vivo, que llama al mismois_allowed. Ahora los tokens vacíos se omiten, de modo que un grupo así no nombra a nadie y se aplica el grupo comodín; el grupo con nombre más específico sigue ganando, y un robots.txt que no nombra a nadie sigue significando que todo está permitido.CorregidoFuncionaCorrige cuatro defectos de selección de exportaciones y validación de ejecuciones que
permitían a una auditoría presentar un resultado que no podía sostener…
El matcher de
internal_allsolo exigía el token de nombre de archivointernal, así que una pestaña Internal parcial por tipo (por ejemplointernal_html.csv, sin ninguna fila que no fuera HTML) satisfacía la exportación maestra obligatoria Internal:All sin ninguna advertencia de maestro ausente; ahora también exigeall.discover_exportselegía el primer candidato para una clave lógica en orden alfabético cuando dos archivos coincidían con ella (por ejemplo,internal_all.csveinternal-all.csvpresentes a la vez con filas distintas), descartando en silencio el otro sin que nada en los metadatos de la ejecución indicara que hubo una elección; ahora lanza un error que nombra a todos los candidatos.run_sfescogía la subcarpeta con marca de tiempo más reciente bajo--outsin importar cuándo se creó, así que una re-ejecución que terminaba con código 0 sin escribir nada (un fallo de arranque que Screaming Frog no informa como salida distinta de cero) podía devolver las exportaciones de una invocación anterior como si fueran frescas; ahora compara con una instantánea tomada antes de que arranque el proceso y falla de forma ruidosa cuando no aparece nada nuevo.build_commandañadía--auth-configsolo cuando el archivo de perfil indicado ya existía, con lo que un rastreo arrancaba en silencio sin autenticación ante una ruta mal escrita o borrada; eso es apropiado para el perfil opcional por defectoseospiderconfig, pero incorrecto para un perfil que la persona que llama pidió de forma explícita. Ahora, unsf_cli.auth_configexplícito que falta lanza un error antes de que arranque Screaming Frog.CorregidoFuncionaCorrige dos defectos de extracción de contenido en
seohead/checks/parser.py(#138,#140).
collapse_whitespacevolvía a decodificar entidades HTML sobre la decodificación única que el parser lxml de BeautifulSoup ya hace en cada valor detag.get_text()/tag.get(attr)que entrega a ese helper: un no-op silencioso en el marcado corriente, pero en una página cuyo CMS o pipeline de importación ya había escapado dos veces sus entidades (un artefacto real y frecuente) convertía una sopa de entidades visiblemente rota en texto de aspecto limpio y acortaba la longitud informada por debajo de lo que de verdad muestra una pestaña del navegador o un snippet de SERP, invirtiendo en ambos sentidos las comprobaciones de longitud de title y description. El helper ya no decodifica nada. Por otro lado, la extracción de enlaces y de URL de origen recorría todo el documento sin condiciones, así que un<a>/<img>que existía solo dentro de un<template>inerte (nunca parte del documento renderizado según la especificación HTML, y nunca solicitado por un navegador ni por un rastreador salvo que un script lo clone) se informaba como enlace real de la página yspider.pylo descargaba de verdad: el mismo fallo de URL fantasma que se cerró para<base href>en #4. Ambos extractores ahora omiten los descendientes de<template>.<noscript>se deja deliberadamente accesible ahí, a diferencia de la extracción de texto: es marcado de respaldo real y definido por la especificación, que un cliente con JavaScript desactivado (y la pasada de rastreo sin renderizado de los buscadores) sí carga, y excluirlo ocultaría al auditor una URL que de verdad se puede descargar. El recuento de palabras tampoco cuenta ahora el texto de los descendientes de<svg>/<math>(el<title>de accesibilidad de un sprite de iconos, el<text>de un glifo, la notación MathML) como contenido del cuerpo: una cabecera con 20 iconos podía duplicar el recuento de palabras de una página frente a su contenido real. Esa lista de exclusión vive ahora en un solo lugar,content_area.TEXT_EXCLUDED_TAGS, compartida por ambos extractores de texto en lugar de dos copias que ya se habían desincronizado.CorregidoFuncionaConserva los tokens
relcompletos de un enlace, su atributotargety su href bruto(sin resolver), y extrae los elementos
<form>: método, action y si hay campo de contraseña (#125). Seis incidencias catalogadas dependían de que se descartaran esos tres datos: enlaces cruzados de origen inseguros (target="_blank"sinrel="noopener"/"noreferrer"), enlaces relativos al protocolo (//host/path, antes de resolver), enlaces salientes a localhost, una página que recibe a la vez un enlace interno seguido y otro nofollow, una action de formulario insegura y un formulario de contraseña servido desde una página HTTP sin cifrar. Las seis son ahoraUNSAFE_CROSS_ORIGIN_LINK,PROTOCOL_RELATIVE_LINK,OUTLINK_TO_LOCALHOST,FOLLOW_AND_NOFOLLOW_INLINKS,FORM_URL_INSECUREyFORM_ON_HTTP_URLen el registro. Las comprobaciones de formulario, localhost y mezcla de nofollow solo necesitan campos que cada rastreo ya registraba, así que esas cuatro se ejecutan siempre; el par de enlaces cruzados y de enlaces relativos al protocolo necesitalink_attributes.capture, desactivado por defecto, porque los datos extra por enlace subieron alrededor de un +50 % en un rastreo sintético de 3387 páginas con 150 enlaces por página: unos +95 bytes por enlace, +46 MiB en total, de los queraw_hrefpor sí solo representa la mayor parte. El registro pasa de 121 a 127 comprobaciones.CorregidoFuncionaCorrige que
report-buildrenderice en silencio un informe sin hallazgos para unanálisis de SF Analyzer…
Corrige que
report-buildrenderice en silencio un informe sin hallazgos para unaudit.jsonde SF Analyzer (#151). La receta documentada (sf run --taskscanalizado areport-build --format docx/xlsx/csv/md) leía las clavesfindingsy las claves planas de página, que el esquema de SF no usa (los hallazgos viven bajoissuesy los datos de página bajopages[].metrics); el desajuste producía un resumen0/0/0/0con seguridad para una auditoría que sí encontraba incidencias críticas reales, sin secciones de hallazgos. Ahorabuild_reportreconoce tanto la forma nativaseohead.site-audit/1como la de SF Analyzer, y normaliza la segunda en el contrato plano que ya entienden los cuatro escritores para personas antes de renderizar.--format jsonno cambia: ya devolvía correctamente el documento original, y eso demostró que los datos nunca faltaron. Un documento que no coincide con ninguno de los dos contratos se rechaza conok: Falsey un nombre del desajuste de esquema, en lugar de renderizarse como un entregable vacío, y se elimina el condicional muertoif ... : passque parecía una validación pero nunca hacía nada.tests/test_docs_commands_execute.pycompara ahora el resumen renderizado de la receta documentada con los totales del propioaudit.json, no solo su código de salida.CambiadoFuncionaCierra dos brechas de seguridad de dinero en
seohead/data_sources/(#157, #159).geo_guardcomprobaba solo la cadena orientativacountry, así quesearch_volume/keyword_ideas/keyword_difficulty/serppodían seguir llegando al endpoint en vivo de DataForSEO conlocation_code=2643(Rusia) o2112(Bielorrusia) siempre que quien llamaba diera el geo-objetivo numérico sin rellenar tambiéncountry; ahora la guarda comprueba primerolocation_code, porque es el campo que realmente se factura. Además, un error a nivel de red (URLError/TimeoutError/SSLError) durante una llamada facturada (elpostde DataForSEO, el/setde Arsenkin ywordstat.topRequests/wordstat.dynamics/web.searchAsyncde Yandex Cloud) reintentaba la misma carga sin clave de idempotencia y solo registraba el intento que finalmente devolvía una respuesta. Ninguno de los tres proveedores ofrece un mecanismo de idempotencia para esos endpoints, así que ahora una respuesta perdida no se reintenta: el intento se registra en el libro de gasto (coste desconocido, marcado comoattempt_failed: network_error) y la llamada falla sin más, en lugar de arriesgar un segundo cargo. Las lecturas idempotentes (/check//getde Arsenkin, el sondeo de operaciones de Yandex Cloud) no cambian y siguen reintentando.yandex_cloud.WebSearch.search_batchaísla un envío perdido en su propia consulta en lugar de abortar el lote.metrika.pyreintenta los errores de red de la misma forma, pero no es dinero facturado y no se modificó; queda señalado para un seguimiento si la creación de sus exportaciones de Logs API debe recibir el mismo tratamiento por motivos de cuota.CambiadoFuncionaCierra una brecha de DNS rebinding en
http_client()(#142):pinned_target(), lacorrección de la ventana TOCTOU descrita en #14, protegía solo la descarga en modo lista de
collect.py: las otras catorce llamadas, incluido el motorcrawl-sitedespider.py, dejaban que httpx resolviera el DNS una segunda vez, de forma independiente, para abrir el socket. Así, un resolutor hostil que respondiera a esa segunda consulta de forma distinta a la de la propia guarda podía alcanzar169.254.169.254o cualquier dirección RFC 1918, sin importar el veredicto de la guarda. Ahorahttp_client()construye cada cliente sobre un transporte que fija la conexión a la dirección que resuelve por sí mismo, tanto en la primera solicitud como en cada salto de redirección, conservando el nombre de host solo para la cabeceraHosty para el SNI de TLS; así la corrección es estructural y no una disciplina que cada llamador debía recordar.SEOHEAD_ALLOW_PRIVATE_NETWORKS/SEOHEAD_ALLOW_PRIVATE_HOSTSno cambian.CorregidoFuncionaCorrige el contrato de códigos de salida CLI/MCP para un fallo que el propio handler
notifica, y completa el conjunto de flags de origen…
Corrige el contrato de códigos de salida CLI/MCP para un fallo que el propio handler notifica, y completa
SOURCE_FLAGS(#155, #156). Un handler que devuelve{"ok": false, ...}(la forma documentada de la capa de herramientas para informar de un fallo de descarga, parseo o proveedor sin lanzar excepción) imprimía ese JSON y salía con código 0 en la CLI, y devolvía un resultado normal (noisError) por MCP, así que una canalización que dependía de$?o un cliente que solo comprobabaisErrorno podían detectarlo. Ahoracli.pysale con código 1 en ese caso (el código 2 delog-scanpara una ejecución que se contradice sigue siendo una señal aparte y documentada, véasedocs/USAGE.md), ymcp_server.pylanzaToolErrordesde un envoltorio compartido_checked(), de modo que el cliente veisError. Ambos llaman a una únicahandlers.handler_failed(), para que las dos interfaces no diverjan sobre qué cuenta como fallo. Por otro lado, aSOURCE_FLAGSse le añadieron--phrase,--keywords,--query/--queries,--seed,--countery--before/--after: cada uno ya identifica la entrada completa de un comando igual que hace--url, pero faltaban, así que un bucle por línea sobre cualquiera de ellos procesaba en silencio solo su primera línea. El conjunto se construye ahora con_source_flag()en el punto donde se declara cada flag, en lugar de enumerarlo a mano por separado, para que no pueda desincronizarse de nuevo.CambiadoFuncionaAmplía
docs/scenarios/de diez cadenas a cincuenta y seis, agrupadas por la preguntacon la que llega quien lee (#120). Qué escenarios existen lo decide el mapa de cobertura y no el gusto: cada uno declara las incidencias catalogadas que resuelve, y
tests/test_scenario_coverage.pyafirma que cada incidencia que esta herramienta dice encontrar aparece en al menos un escenario, que ningún escenario nombra una incidencia que el mapa no lista y que ninguno omite sus límites. Las 143 incidencias detectables están cubiertas. Cada comando de cada archivo se sigue ejecutando en CI contra el sitio de prueba: la suite ejecuta 2008 pruebas, de las cuales la puerta de comandos de documentación es ahora el grupo más grande.CambiadoFuncionaAfirma los límites del propio protocolo sitemap (#124):
SITEMAP_TOO_MANY_URLSporencima de 50 000…
Afirma los límites del propio protocolo sitemap (#124):
SITEMAP_TOO_MANY_URLScuando hay más de 50 000 entradas en un archivo,SITEMAP_TOO_LARGEpor encima de 50 MB sin comprimir, ySITEMAP_URL_DUPLICATEDpara una URL declarada en más de un sitemap, nombrando ambos documentos. Un archivo que supera cualquiera de los límites es inválido, no solo grande: un buscador puede leer una parte y descartar el resto sin que el titular del sitio vea nada, y los umbrales vienen del protocolo, no de la configuración. Ambos parsers registran ahora el tamaño en bytes y el número declarado por documento, y los hallazgos nombran el sitemap hijo en lugar del índice. El registro pasa de 118 a 121 comprobaciones.AñadidoFuncionaAñade
docs/GUIDELINE.md, el documento que una persona lee primero (#121): qué es esto yqué no es, una primera ejecución de principio a fin, cómo elegir la tasa de rastreo y cómo saber si los errores son tuyos, cómo leer
audit.jsonsin que te induzca a error, qué cambia el archivo de configuración y qué solo cuesta, los seis errores que todo el mundo comete al principio, qué hacer cuando la herramienta se equivoca y qué no puede responder en absoluto. Enlazado en primer lugar desde el README, por delante de la referencia.AñadidoFuncionaAñade
docs/COVERAGE_SF_ISSUES.md, generado desdeseohead/sf/core/sf_issue_map.py:cada una de las 320 incidencias del catálogo publicado del sector, con exactamente un estado (encontrada por una comprobación con nombre, encontrada por un comando con nombre, encontrada en parte con la parte que falta indicada, una brecha con nombre o una decisión con su motivo). (#119) De las 212 incidencias dentro del alcance, 126 se encuentran hoy y 17 en parte; 41 son brechas y 28 necesitan algo que deliberadamente no se construyó. Accesibilidad (92) y AMP (16) se descartan como decisiones únicas, con sus listas completas a la vista para que la decisión sea auditable. Una prueba verifica que cada ID de comprobación y cada comando referenciados siguen existiendo, de modo que un cambio de nombre rompe la compilación en lugar de dejar el documento desactualizado. Sustituye a
docs/CHECKLIST_AUDIT.md, que se escribió sin tener el catálogo a mano.CambiadoFuncionaEl sembrador de sitemap solicita la dirección que publicó el sitemap, no su forma
normalizada (#115).
sitemap.crawl()devolvía solo ellocnormalizado, así que un sitemap que declaraba/a/provocaba una descarga de/a: en la mayoría de los CMS, un 301 que el rastreador inventaba y después informaba como hecho sobre el sitio, y un 404 allí donde la forma sin barra final ni siquiera está enrutada. Cada entrada lleva ahoraloctal como se publicó, junto aloc_normalizedpara los consumidores que comparan por él. Las estadísticas de redirección de rastreos anteriores sembrados desde sitemap son sospechosas por esta razón.CambiadoFuncionaReestructura la skill de operador en un directorio controlador (#111).
.claude/skills/tiene ahora dos niveles: 21 skills de método, cada una cubre bien una sola cosa, ycontrol/, que decide cuáles de ellas ejecutar en un sitio que nadie ha revisado todavía. El controlador enruta en lugar de repetir, y contiene cinco sub-skills cargables (alcance, tasa y carga, lectura de una auditoría, verificación y entregables) y un archivo de referencia de tres ficheros (defectos encontrados en sitios reales y qué los delató, qué población describe cada comprobación, y qué no puede responder en absoluto el toolkit). Las comprobaciones de solo inglés y de comandos de documentación cubren ahora cada archivo Markdown bajo un directorio de skill, no soloSKILL.md.AñadidoFuncionaAñade
tests/chains/: un sitio de prueba construido con las formas que realmente rompenlas cadenas —…
Añade
tests/chains/: un sitio de prueba construido con las formas que realmente rompen las cadenas (las dos formas con barra de una misma URL, un cuerpo que no es UTF-8 válido, una página windows-1251, una cabecera de sitio fuera de<main>, un enlace a otro host, una ruta bloqueada por robots), rastreado por loopback, con diecisiete aserciones sobre la ejecución completa y no sobre un módulo concreto (#112). Cuatro propiedades: conservación (un número no cambia de significado al viajar), población (un hallazgo trata sobre un miembro del conjunto que describe), determinismo (dos rastreos, dos niveles de concurrencia, una sola respuesta) y representación (una página indica cómo se midió). Las reglas de población son las propias delogscan, así que una contradicción que el escáner puede nombrar es una prueba de cadena que la afirma.CambiadoFunciona
reconcile_sitemapinforma de cada URL tal como se escribió, no tal como se normalizó.La comparación sigue haciéndose sobre la clave normalizada, pero un hallazgo que nombraba una forma normalizada citaba una URL que no aparecía en ningún lugar del rastreo: inaccionable para quien lee e indistinguible, para el escáner de anomalías, de un hallazgo sobre una página nunca descargada.
AñadidoFuncionaAñade
docs/scenarios/: diez cadenas de extremo a extremo, cada una con los comandosreales en orden, el artefacto que sale, lo que cuesta y lo que esa cadena no puede responder (#110). El resto de la documentación enumera lo que tiene el toolkit; esto describe lo que hace. Enlazado desde el README por encima de la lista de herramientas, de modo que quien evalúa el repositorio encuentra primero las cadenas y después el inventario. Cada comando mostrado se ejecuta contra el sitio de prueba mediante
tests/test_docs_commands_execute.py, cuyo extractor y cuyas puertas de solo inglés y de recuento recorren ahoradocs/en todos sus niveles, no solo en el superior.AñadidoFuncionaAñade
log-scan(CLI) yseo_log_scan(MCP): lee los propios artefactos de unaejecución terminada y…
Añade
log-scan(CLI) yseo_log_scan(MCP): leen los propios artefactos de una ejecución terminada e informan de afirmaciones que no pueden ser ciertas a la vez (#109). Ocho reglas, cada una escrita a partir de un defecto que llegó a producción pasando por toda la suite de pruebas: un tamaño registrado que no coincide con el archivo en disco, una proporción de texto por encima del 100 %, una comprobación que se dispara más veces de las que hay páginas donde disparar, un hallazgo sobre una URL que la ejecución nunca descargó, una canonical tratada como redirección mientras esa URL respondía 2xx en la misma ejecución, un resumen que no coincide con sus propias filas, palabras contadas en una página de cero bytes y páginas medidas de dos formas cuando solo algunas dicen cuál. Cada anomalía nombra ambos valores y de dónde se leyó cada uno. La CLI sale con código 2 cuando una ejecución se contradice, para que una canalización se detenga en lugar de publicar las cifras.CambiadoFuncionaEl test de pacing entre workers ya no mide el reloj de pared (#107).
_DispatchGatelee ahora el reloj inyectado del rastreo en lugar de llamar directamente atime.monotonic(), así que la prueba lo maneja con un reloj virtual que avanza solo cuando algo duerme: los instantes de despacho son la aritmética propia del rastreador y la aserción es exacta. La forma anterior comparaba intervalos reales transcurridos con un mínimo de 0,024 s y fallaba sin que el código cambiara siempre que la máquina estaba ocupada.CambiadoFuncionaCierra la segunda mitad de la auditoría de ajustes no conectados (#91).
http.headersse combina en cada solicitud junto a las cabeceras de credencial;speed.adaptivecontrola el retardo y el ajuste de concurrencia del throttle (los contadores de timeouts y de errores de servidor siguen funcionando, porque dejar de reintentar es un mecanismo aparte de retroceder);discovery.hyperlinks.store/.crawl,discovery.external.storeydiscovery.redirects.crawldeciden ahora qué registra el rastreo y qué sigue.discovery.canonicals.*,discovery.external.crawlydiscovery.redirects.storese eliminan en lugar de conectarlos: nombraban una capacidad que el spider no tiene (seguir canonicals, rastrear entre hosts) o un estado que no puede retener, y un ajuste que aparece en--config-helpy en el manifiesto de la ejecución sin cambiar nada es peor que no tener ajuste. La lista de excepciones del canario de cobertura queda ahora vacía: cada ruta deDEFAULTScambia un resultado observable y un test la nombra.CambiadoFuncionaDetectar el área de contenido a partir de la semántica del propio documento cuando no hay
nada configurado (#96): primero
main, después[role="main"]y luegoarticle, y registrar cuál coincidió comoauto_main/auto_role_main/auto_article. El valor anterior por defecto —todo el body menos las etiquetasnavyfooter— contaba 126 palabras de plantilla de un total de 433 en una entrada real de WordPress en directo (29 %), incluido un enlace de «saltar al contenido». Esa inflación afectaba en la misma dirección aTHIN_CONTENTyLOW_TEXT_RATIOen todas las páginas de una plantilla.headeryasidese suman anavyfooterenDEFAULT_EXCLUDE_TAGSpara la vía de respaldo. Un selector configurado sigue teniendo prioridad, y si no coincide con nada, se recurre afallback_default_bodyen lugar de detectar en silencio otra región.CambiadoFunciona
URL_NOT_IN_SITEMAPahora compara páginas con páginas (#94).Antes comparaba las URL de un sitemap con todos los destinos del grafo de enlaces del rastreo. Así, en un sitio real de 124 páginas se activaba 392 veces: 362 archivos de imagen a los que una galería enlaza directamente, cinco enlaces a otros hosts y 30 URL que el rastreo nunca descargó. Eso suponía el 74 % de ese informe y ocultaba las incidencias reales. Ahora el lado observado son las páginas que un sitemap debe declarar: descargadas, con respuesta 2xx, HTML, del mismo host e indexables.
reconcile_sitemaprecibe esa población como argumentocomparableseparado, así queSITEMAP_ORPHANsigue comprobando la accesibilidad frente a todos los destinos de enlace y no puede inventar huérfanos. Lo que se descarta se devuelve enlinked_not_comparableen lugar de eliminarse.CorregidoFuncionaCorregir las comprobaciones de canonical en un sitio que sirve las dos formas de una URL,
con y sin barra final (#95).
norm_urlelimina la barra final a propósito, así que un canonical escrito sin ella coincide con la página que sí la tiene. Pero el índice normalizado guardaba solo una página por clave, y un rastreo de un sitio WordPress típico tiene dos:/x(301) y/x/(200). Leer la que se insertó primero hacía queCANONICAL_TO_REDIRECTmarcara 78 páginas activas cuyo canonical responde 200.AuditContextahora exponepages_by_normcon todas las páginas bajo cada clave,page_by_normdevuelve la variante que respondió 2xx, yCANONICAL_TO_REDIRECTyCANONICAL_NON_INDEXABLEsolo se activan cuando ninguna variante los contradice.CorregidoFuncionaCorregir
size_bytes: ahora es el cuerpo de la respuesta tal como llega por la red,medido antes de decodificarlo (#99). Antes se medía a partir de la cadena ya decodificada, así que cada byte que no era UTF-8 válido se convertía en U+FFFD y se volvía a codificar como tres bytes. Un WebP de 739 KB de un rastreo real se registraba como 1,27 MB, y el factor de inflación variaba de un archivo a otro. Se sobrestimaban imágenes, PDF, fuentes y HTML servidos en un juego de caracteres heredado (windows-1251), y también el ratio de texto calculado sobre ese denominador. La caché HTTP guarda el tamaño en red junto con la entrada, así que una página reproducida informa lo mismo que informó la descarga en vivo. Su esquema pasa a
http_cache.v2, y las entradas v1 se vuelven a descargar una vez en lugar de reproducirse sin tamaño.AñadidoFuncionaAñadir
docs/TOOL_REFERENCE.md, generado a partir de las definiciones de herramientasMCP (
seohead/mcp/tool_reference.py,scripts/generate_tool_reference.py): los argumentos de cada herramientaseo_*/sf_*con su tipo y valor por defecto, su coste (red, escrituras, idempotencia, gasto; se lee de su perfilToolAnnotations) y las notas sobre comportamiento y modos de fallo de su propia docstring.tests/test_docs_drift.pyhace fallar la compilación si el documento se desvía de las definiciones de herramientas o si falta alguna herramienta.AñadidoFuncionaAñadir
tests/test_docs_commands_execute.py: extrae cada comandoseohead ...queaparece en README, docs, skills y ejemplos (
scripts/doc_commands.py) y lo ejecuta sin conexión, contra un sitio de prueba en bucle local (tests/doc_fixtures/) y contra copias materializadas deexamples/, comprobando que termine sin errores. Los comandos que necesitan infraestructura real (RDAP/DNS, un binario de SF con licencia, una credencial de proveedor de pago, el servidormcp, que nunca termina) al menos se analizan con el parser de argumentos en vivo. Un comando documentado que deja de funcionar ahora hace fallar la CI en lugar de publicarse desactualizado.CambiadoFuncionaReestructurar las 21 skills técnicas de flujo de trabajo (
.claude/skills/*/SKILL.md)con una forma común: Trigger, Anti-trigger, Preconditions (como lista de comprobación), el Workflow existente, Decision points, Definition of done (como lista de comprobación) y Cost. Corregir el recuento obsoleto de cobertura de comandos al final de
docs/SKILLS.md. El recuento real, calculado escaneando cada archivo de skill, lo verifica ahora una nueva prueba de drift.CorregidoFuncionaCorregir varios recuentos de herramientas y pruebas que se habían desfasado sin avisar de
los registros reales (un recuento…
Corregir varios recuentos de herramientas y pruebas que se habían desfasado sin avisar de los registros reales: un recuento obsoleto de comandos CLI en
docs/USAGE.md,docs/COMPARISON.md,README.mdydocs/TESTING.md, un recuento obsoleto de herramientas MCP endocs/TOOLS.md, un recuento obsoleto de herramientas de referencia endocs/README.mdy el número de pruebas sin conexión. Los valores corregidos quedan fijados con una prueba de regresión (test_stale_tool_counts_do_not_reappear).AñadidoFuncionaAñadir las cuatro auditorías estáticas de Lighthouse que no necesitan navegador ni API de
terceros (#59):
MISSING_CHARSET,MISSING_DOCTYPE,VIEWPORT_MISSINGyNO_COMPRESSION, cada una calculada a partir de evidencia que ya contiene un rastreo.content_encoding,meta_charset,doctypeyviewportse suman al vocabulario normalizado de columnas, de modo que una exportación de SF que los traiga como columnas de Custom Extraction alimenta las mismas comprobaciones. El registro crece de 114 a 118 comprobaciones.CambiadoFuncionaConectar los diez ajustes restantes del rastreador que estaban validados y escritos en el
manifiesto de la ejecución…
Conectar los diez ajustes restantes del rastreador que estaban validados, se escribían en el manifiesto de la ejecución y
--config-helpdescribía, pero que nada leía (#63).limits.max_response_bytes,speed.max_delay_seconds,robots.user_agent_tokenyspeed.stop_after_consecutive_timeoutsahora configuran un comportamiento que antes estaba fijado en el código.robots.unavailable_means_stopdecide si un robots.txt inaccesible o con error 5xx detiene el rastreo o se trata como sin restricciones. Antes, un robots.txt inaccesible nunca detenía el rastreo, sin importar la política, mientras que uno con 5xx siempre lo hacía. Ahora ambos casos son el mismo caso «no disponible», regulado por el ajuste.limits.max_url_length,limits.max_query_variants_per_path,http.retry_on_timeoutydiscovery.follow_nofollowson comportamientos nuevos.http.user_agentse aplica ahora a las peticiones reales, en lugar de enviar siempre el agente por defecto del toolkit. Se añadencrawl-describe-settings(CLI) yseo_crawl_describe_settings(MCP) para que un agente pueda descubrir la superficie de configuración sin acceso al sistema de archivos (#23).AñadidoFuncionaAñadir búsqueda personalizada (
tools/custom_search.py) y extracción personalizada(
tools/custom_extract.py) sobre un corpus ya rastreado: filtros de presencia y ausencia (código fuente sin procesar, texto visible, un elemento CSS con nombre o un nodo XPath) y extractores CSS/XPath/regex. Ambos informan sobre qué representación usaron: marcado estático frente al DOM renderizado. La ausencia se cuenta con honestidad: una página cuya descarga falló se excluye tanto del numerador como del denominador, en lugar de contarse como ausente. La extracción ejecuta cada par (documento, extractor) con un presupuesto de tiempo real (SIGALRMen POSIX). Una expresión patológica aborta solo ese documento, y la ejecución termina igualmente.AñadidoFuncionaAñadir la clasificación de la posición de los enlaces (
tools/link_position.py): nav,cabecera, barra lateral, pie o contenido, mediante una regla ordenada sobre la ruta de ancestros de cada enlace. Reutiliza la noción de contenido de
content_area.pyen lugar de inventar una segunda. Se conecta a la grabación de enlaces decrawl/spider.pytraslink_position.classify(desactivada por defecto, porque guardar una posición por enlace consume memoria en un rastreo grande). Se agrega a nivel de sitio medianteinlink_compositiondecrawl/linkgraph.py, que ahora alimenta una nueva incidencia de auditoría,INLINK_BOILERPLATE_ONLY, para las páginas enlazadas solo desde elementos de plantilla. El registro pasa de 104 a 105 comprobaciones.AñadidoFuncionaAñadir ocho cálculos de segunda pasada tras el rastreo, que solo se pueden responder
cuando este ha terminado…
Añadir ocho cálculos de segunda pasada que solo se pueden responder cuando el rastreo ha terminado (issue #15): una puntuación de enlaces internos calculada a partir del grafo de aristas
all_inlinks(LOW_LINK_SCORE); una URL canónica a la que ningún hipervínculo apunta (UNLINKED_CANONICAL); la detección de bucles y de series sin enlazar enrel="next"(PAGINATION_LOOP,UNLINKED_PAGINATION_SERIES); la reciprocidad de hreflang (HREFLANG_MISSING_RETURN_LINK); agregados de composición de enlaces entrantes (ONLY_NOFOLLOW_INLINKS,ONLY_NONINDEXABLE_SOURCE_INLINKS); la ruta de descubrimiento más corta y concreta desde la semilla del rastreo (DEEP_DISCOVERY_PATH); un respaldo calculado internamente para contenido mixto (INSECURE_SUBRESOURCE); y la agrupación de casi duplicados a partir del texto de página almacenado (NEAR_DUPLICATE/DUPLICATE_BY_HASH). Esta última conecta por primera veztools/duplicate.pyytools/content_area.pya la auditoría.ORPHAN_PAGE,SITEMAP_ORPHANy las dos comprobaciones nuevas de «sin enlazar» ahora se omiten. Se informan como un salto con nombre, no como incidencia, en un rastreo que el agregador ha marcado como parcial, porque «nada enlaza aquí» no se puede demostrar en un rastreo truncado. El registro pasa de 104 a 114 comprobaciones.CambiadoFuncionaAuditar el registro de rastreo frente a una lista externa de SEO técnico y cerrar ocho
huecos baratos y verificados…
Auditar el registro de rastreo frente a una lista de comprobación externa de SEO técnico y cerrar ocho huecos baratos y verificados: cinco comprobaciones de hreflang (códigos de idioma o región no válidos, falta de autorreferencia, falta de x-default, entradas duplicadas y destinos no canónicos), dos directivas de robots (
notranslateyunavailable_after) y URL canónicas que contienen un fragmento. El registro pasa de 96 a 104 comprobaciones. Consultadocs/CHECKLIST_AUDIT.md.AñadidoFuncionaAñadir
asset-weight-check: descarga el CSS/JS enlazado de una página e informa derecursos que bloquean el renderizado…
Añadir
asset-weight-check: descarga el CSS/JS enlazado de una página e informa de los recursos que bloquean el renderizado, los archivos demasiado grandes, las bibliotecas duplicadas (por hash de contenido), la falta de minificación, la ausencia defont-display, el JS polyfilled heredado y la falta de compresión o de caché de larga duración.AñadidoFuncionaAñadir
crawl-site --sitemap <url>(ysitemaps.auto_discoveren--config): alimentarel rastreador nativo con las URL declaradas en un sitemap, seguir los enlaces de cada una y cotejar los conjuntos declarado y observado en
summary.sitemapdeaudit.json. Se usan los mismos identificadores de comprobación,SITEMAP_ORPHAN/URL_NOT_IN_SITEMAP, que ya informa el flujo de Screaming Frog.AñadidoFuncionaAñadir
crawl-site --config-help, generado desdeseohead/crawl/config.py, y ocultar--max-depthy--min-delayen--help(siguen aceptándose), para que la superficie de flags deje de crecer con cada ajuste del rastreador.CambiadoFuncionaDividir la detección de tecnologías (fingerprinting) en un paso de descarga y en un paso
puro
analyze_tech, capturar los identificadores de analítica y de gestores de etiquetas en lugar de solo sus nombres, y añadir un informetag_coverageque agrupa la presencia por plantilla de URL y marca cómo se midió cada página.CambiadoFuncionaResolver cadenas y bucles de redirección como segunda pasada sobre los destinos de
redirección de un rastreo terminado…
Resolver cadenas y bucles de redirección como segunda pasada sobre los destinos de redirección propios de un rastreo terminado. Así,
REDIRECT_CHAIN/REDIRECT_LOOPya no dependen del informe nativo Redirect Chains de Screaming Frog: una exportación con perfil ligero o una ejecución decrawl-siteobtiene las mismas incidencias sin coste adicional.AñadidoFuncionaAñadir un área de contenido configurable (
content_area.py) que limita el recuento depalabras a la región principal, excluyendo de forma predeterminada la navegación y el pie, sin afectar al descubrimiento de enlaces. La estrategia resuelta se informa por página.
CambiadoFuncionaSeparar los duplicados exactos de los casi duplicados en
duplicate.py: lascoincidencias exactas se calculan con hash a partir del texto extraído (no de los bytes en bruto) y se excluyen de los grupos de casi duplicados. Además, las comparaciones solo consideran páginas indexables de forma predeterminada.
AñadidoFuncionaAñadir un informe de consistencia de plantillas (
boilerplate_report.py) que calcula elhash de cabecera, navegación y pie de cada página, y marca los grupos de plantilla minoritarios.
AñadidoFuncionaAñadir extracción de Markdown sin dependencias (
markdown_extract.py): una renderizaciónsolo del área de contenido y otra del documento completo.
CambiadoFuncionaConectar
markdown_extractyboilerplate_reporta la CLI y a la superficie MCP comomarkdown-extract/seo_markdown_extractyboilerplate-report/seo_boilerplate_report(47 herramientas básicas, frente a 45 antes). Además, añadir a la firma MCP deseo_duplicate_checkla marcaonly_indexable, queduplicate_checkya tenía en la capa de handlers y donde se había pasado por alto. La ruta de URL decitability-checkpasa a usar el Markdown del área de contenido demarkdown_extracten lugar del campotextdel parser. Ese campo es el documento entero, una sola línea colapsada sin saltos de párrafo ni de encabezado. Con este cambio se corrigen dos problemas: la dilución por plantilla que planteaba el issue y un error latente. El texto plano anulaba en silencio las dimensiones Answer Blocks y Structure Quality en cada URL en directo. Sin limitar a propósito quedaron dos cosas. La primera es el propio campotextdel parser, que sigue siendo de todo el documento, porque la extracción de evidencia de esquema depage_facts.py(enlaces socialessameAs, migas de pan, expresiones regulares de precio y valoración) depende de datos que legítimamente viven en los widgets de cabecera y pie que el área de contenido excluye. La segunda son las comprobacionesTHIN_CONTENT/LOW_TEXT_RATIOdesf/core/rules.py, cuyosword_count/text_ratiovienen de las columnas de exportación de Screaming Frog. Son datos de terceros que el toolkit no puede reducir sin HTML en bruto, lo que obligaría a descargar de nuevo cada página y rompería el diseño offline sin peticiones de la auditoría SF. El crawler propio (crawl-site) ya hereda el alcance del área de contenido sin coste, porque su recuento de palabras se lee directamente deparser.parse_html.CambiadoFuncionaDocumentar una convención de nombres (
docs/NAMING.md) y resolver las colisiones denombres base de módulo y los archivos de prueba nombrados por proceso que se encontraron. No cambió ningún nombre de comando CLI, handler ni herramienta MCP.
AñadidoFuncionaAñadir archivos de incorporación para la comunidad, las citas y los agentes que no
necesitan clave.
AñadidoFuncionaAñadir la skill de flujo de trabajo con permisos
analytics-console-reviewy tresrecetas prácticas.
- CambiadoFuncionaDocumentar el soporte de la línea de seguridad actual
3.x. CambiadoFuncionaExigir TLS 1.2 o superior y fijar las sondas directas de certificados a direcciones
públicas ya validadas.
AñadidoFuncionaAñadir una caché de respuestas HTTP para
crawl-site(seohead/crawl/cache.py,activable mediante
cache.mode; por defectooff, para que ningún efecto secundario quede oculto tras un valor predeterminado). Incluye semántica real de frescura HTTP (max-age/Expires, revalidación conETag/Last-Modified, variantes sensibles aVary, y respeto deno-store/no-cache). Un modoreplaysirve para depurar; queda reflejado en el manifiesto y nunca es el valor por defecto. Un flaginvalidatefuerza una recarga explícita. Cada página descargada llevacache_status(hit/revalidated/miss). La ejecución llevacache_statsycache_replaytanto en la salida del handler como en el bloquerundeaudit.json, de modo que un informe construido en parte desde la caché lo indica. Un acierto de caché no cuesta ninguna petición ni consume el retardo de throttle ni un hueco del gate de envío concurrente: la espera se emite desde dentro defetch_one, solo cuando está a punto de producirse una ida y vuelta real a la red.AñadidoFuncionaAñadir reutilización basada en el journal a
seohead/core/runlog.py(
SEOHEAD_REUSE_POLICY, una edad máxima por herramienta…Añadir reutilización basada en el journal a
seohead/core/runlog.py(SEOHEAD_REUSE_POLICY, una edad máxima en segundos por herramienta; por defecto vacía, lo que significa que nunca se reutiliza nada). Una respuesta anterior configurada, todavía fresca y correcta, se devuelve en lugar de volver a llamar a la herramienta. Se marca conreused: trueyreused_from_ts, tanto en el resultado como en la nueva entrada del journal que sigue escribiéndose. La frescura siempre se mide desde el momento en que el valor se obtuvo de verdad, y la propia reutilización nunca la prolonga.
3.0.0
Primera instantánea pública30 de agosto de 202610 entradas · Primera instantánea pública10 cambiado
30 de agosto de 2026
10 cambiado- CambiadoFuncionaUn único paquete de Python con 42 herramientas CLI/MCP compartidas.
CambiadoFuncionaCinco herramientas MCP adicionales de Screaming Frog y un analizador de rastreo con 96
comprobaciones.
CambiadoFuncionaReconocimiento de dominio, CDN, tecnología, seguridad, espejos, regiones, bots y
backlinks.
- CambiadoFuncionaValidación de Schema.org y generación de grafos de datos conectados.
CambiadoFuncionaEvidencia del sitio acotada a partir del sitemap e informes en XLSX, DOCX, CSV, Markdown
y JSON.
- CambiadoFuncionaIntegraciones opcionales con Wordstat, SERP de Yandex, Arsenkin, Metrika y DataForSEO.
- CambiadoFuncionaVeintiuna skills técnicas de flujo de trabajo y siete playbooks de SEO empaquetados.
- CambiadoFuncionaMCP local por stdio y soporte de Docker; sin GUI, API alojada ni telemetría.
CambiadoFuncionaREADME público basado en evidencias, con visuales reproducibles de auditoría sintética,
tareas, interfaz e informes.
- CambiadoFuncionaPublicación sin historial y avisos explícitos de terceros.
Fecha = el día en que llegó el cambio (fecha git de su fragmento changelog.d/). Número = el issue que cierra. Título = primera frase, detalles al hacer clic.