Журнал изменений
Что изменилось в SpiderHead, релиз за релизом. Каждая запись указывает тип изменения и работает ли оно уже сейчас.
Unreleased
С 3.1.065 записей22 октября 2026 г.
7 изменено2 исправленоИзмененоРаботаетA results difference between two scans can now be attributed.#1529
The new read-only
#1529 (задача на 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.ИзмененоРаботаетA native crawl now measures its own reading level.#1516
The new
#1516 (задача на 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.ИсправленоРаботаетCrawls on hosts that enforce https no longer spend a redirect hop on every http URL.#1484
The new opt-in
#1484 (задача на 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.ИзмененоРаботаетA crawl started deep can now stay in its own subtree.#1481
The new
#1481 (задача на 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.ИсправленоРаботаетPages 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 (задача на 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.ИзмененоРаботаетAn 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 (задача на 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.ИзмененоРаботаетHrefs 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 (задача на 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.ИзмененоРаботает
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 (задача на GitHub)axe.heading_orderbehaviour the check was modelled on. Evidence rows carry from/to levels and texts for both directions.ИзмененоРаботаетThird-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 (задача на GitHub)
21 октября 2026 г.
3 добавлено4 изменено3 исправленоИзмененоБетаДесктоп: набор URL как плоский список или дерево путей.#1492
Переключатель «список / дерево» в конце панели групп переводит набор данных между плоской таблицей и сворачиваемым деревом путей, построенным по тем же строкам и фильтрам: хосты — верхние узлы, каталоги URL — собственные папки-листья, документы висят на последней папке. Выбор листа управляет общим выделением таблицы, поэтому детали и фильтры сохраняются при переключении.
#1492 (задача на GitHub)ДобавленоБетаДесктоп: режим просмотра только данных.#1495
View > Data only (Ctrl+Alt+D) скрывает навигацию и верхнюю панель для длинных сессий проверки и оставляет только данные. Выбор сохраняется в пределах сессии; панели каждого экрана по-прежнему управляются своими переключателями.
#1495 (задача на GitHub)ИсправленоБетаЛоги: время ответа принимается в любой позиции и в раскладках с одним ident.#1534
Парсеры Apache теперь извлекают referer, user-agent и time-taken, если время ответа стоит между размером и referer или в конце строки, а не молча отбрасывают оба поля в кавычках. Определение формата принимает один или два ident-токена между IP клиента и временной меткой, поэтому пользовательская раскладка nginx с одним дефисом импортируется, а не проваливает весь импорт. Отчёт импорта называет принятые варианты (combined-2-ident, combined-1-ident). Закрывает #1534 и #1535.
#1534 (задача на GitHub)ИзмененоБетаДесктоп: шкала отступов завершена — нигде нет полей вне шкалы.#1374
Оставшиеся 184 вызова setContentsMargins/setSpacing вне шкалы в 60 файлах переведены на токены шкалы с правилом «только уменьшать»; ратчет-тест теперь падает на любом значении вне шкалы. Сначала нормализовали поиск, изображения, входящие, проблемы, логи, журнал и онбординг.
#1374 (задача на GitHub)ИзмененоБетаДесктоп: мелкие улучшения — сырые значения TSV, проект в заголовке окна, контраст
третичного текста.
copy_tsv вставляет сохранённые значения, поэтому видимая заглушка «нет данных» не попадает в таблицу; в заголовке окна указан открытый проект (Project — SpiderHead); третичный текст теперь проходит контраст AA на приподнятых поверхностях.
ИсправленоБетаДесктоп: честные области клавиатуры, Return открывает детали, понятные источники ошибок.
F6 переключает только навигацию и текущую страницу; Return открывает детали выбранной строки, как и обещало меню строки; ошибки чтения в строке состояния называют операцию (таблица URL, параметры сканирования), а не сырой идентификатор запроса.
ИзмененоБетаДесктоп: меню «Вид» привязано к панелям текущего экрана.
Экран может отдавать panel_actions() — тройки (название, показан ли, переключатель) — и меню «Вид» строит раздел панелей по экрану при его открытии. Экран URL предлагает свою сводку запуска и режим только таблицы; устаревшие пункты аудита остаются на своей странице.
ИсправленоБетаДесктоп: сигналы активности больше не заливают логи закрытых окон.
Глобальный сигнал активности продолжал обращаться к удалённым виджетам BusyIndicator; закрытые окна теперь молчат.
ДобавленоБетаДесктоп: вкладки простого режима можно скрывать и возвращать.
Контекстное меню полосы вкладок: скрыть вкладку, вернуть скрытые, показать все; выбор сохраняется. Первая вкладка всегда остаётся, последнюю видимую скрыть нельзя, а скрытая вкладка появляется сама, когда «Обзор» на неё переходит.
ДобавленоБетаДесктоп: состояния простого режима, фирменная панель инструментов и офлайн-снимки.
Панели состояний с действиями: нет результатов (очистить поиск / показать все), сбой (повторить / открыть лог), ядро не найдено (открыть настройки); уведомление об остановке учитывает просканированные и поставленные в очередь URL. На панели инструментов — фирменный знак-паук, а счётчик ошибок выведен бейджем.
20 октября 2026 г.
1 добавлено3 измененоИзмененоБетаПакет CLI
seoheadразбит на модули по доменам.#1514
#1514 (задача на GitHub)cli/_shared.pyхранит реестры команд и помощники ввода;checks_cmds,project_cmds,scan_cmds,crawl_cmds,sources_cmds,reports_cmdsиmisc_cmdsсодержат каждый свою часть прежнего сопоставления аргументов kwarg, флагов argparse и особых случаев диспетчера изcli/__init__.py. Публичная поверхность импорта не изменилась, а модуль сократился с 4 506 до 513 строк; вывод--helpостаётся побайтно одинаковым для каждой команды.ИзмененоБетаОбработчики MCP вынесены в отдельный пакет handlers.#1514
Серверные обработчики теперь лежат в
#1514 (задача на GitHub)seohead/mcp/handlers/и разделены по доменам: проекты, трафик, логи, источники, контент, семантика, workflow, сохранённые сканы, доказательства и экспорт BI, окружение и каталог. Ссылки на документацию и пути к исходникам обновлены под новую структуру.ИзмененоБетаТаблица URL: множественное выделение с копированием TSV по выделению.#1347
Доработка таблицы URL из #1347: выделите несколько строк и скопируйте в TSV ровно выделенное.
#1347 (задача на GitHub)ДобавленоБетаЯдро управления скоростью сканирования в реальном времени (в работе).#1360
Ядро, которое позволяет менять скорость сканирования во время скана (#1360); подключение в десктопе будет следующим.
#1360 (задача на GitHub)
Более ранние дни (4)Show all
14 октября 2026 г.
3 измененоИзмененоБетаДесктоп: прогресс скана, лимит URL, кнопка остановки и причины завершения.#1358
Выполнено / в очереди / скорость / ETA и запрошенный лимит URL показываются в списке сканов, в деталях скана и в карточке навигации. Кнопка остановки в верхней панели подписана «Stop scan» вместо идентификатора запуска, обновляется без мерцания и скрывается, когда запуск завершён; завершённые запуски объясняют, почему остановились (лимит URL, запросов или времени, ошибки, диск).
#1358 (задача на GitHub)ИзмененоБетаДесктоп: единая система кнопок, стандартные поля страниц, без неактивных чипов.
Единая система кнопок во всех экранах, стандартные поля страниц; чипы недоступных функций убраны.
ИзмененоБетаДесктоп: генератор редиректов и редактор сниппетов переехали в раздел «Инструменты».
В «Методах» остался только каталог методов, при открытии он показывает выбранный скан; редактор сниппетов по умолчанию выбирает контекст выбранного скана.
13 октября 2026 г.
3 измененоИзмененоРаботаетДесктоп-краулер: вкладки деталей URL (inlinks, outlinks, ресурсы, сниппет, сохранённый#1349
исходник, заголовки) поверх файла сканирования, фильтры по каждой вкладке со счётчиками, более полный обзор с директивами, выбор колонок для каждой вкладки, связанный с колонками экспорта, сортировка по заголовкам, контекстное меню и навигация с клавиатуры; «Новый скан» может сохранить свои настройки как именованный профиль сканирования.
#1349 (задача на GitHub)ИзмененоРаботаетДесктоп: нерабочие разделы — граф ссылок показывает итоги по узлам, рёбрам и#1347
orphan-страницам и страницу…
Десктоп: нерабочие разделы. Раздел «Граф ссылок» читает итоги по узлам, рёбрам и orphan-страницам и постраничную таблицу узлов из ядерной команды
#1347 (задача на GitHub)scan-graphвместо заглушки. «Проблемы» показывают самые крупные группы проверок по счётчикам ядра; таблица URL показывает и сортирует колонку Inlinks и предупреждает, если скан не сохранил наблюдений по ссылкам. Колонка Issue count, которую невозможно измерить, больше не предлагается. Экспорт и отчёты запускают ядерную командуscan-exportдля страниц или находок в CSV, XLSX, JSON или XML в выбранную папку; наборы данных сравнения и задач, заглушка колонок и история экспорта, которые ядро не может обеспечить, удалены. Настройки, которые сохраняются, но ещё не применяются, теперь видимо отключены с причиной в подсказке. Диалог конфигурации сканирования один раз выводит параметры без проверенного редактора, в режиме «только чтение», а не смешивает их со списком редактора; поле «Why this scan» в «Новом скане» объясняет, почему оно пусто.ИзмененоРаботаетДесктоп: нерабочие разделы — раздел «Краулер» теперь запускает разовое сканирование без#1347
проекта.
Десктоп: нерабочие разделы. Раздел «Краулер» теперь запускает разовое сканирование без проекта. Поле адреса, переключатель Site / List / Sitemap, лимит URL, Start / Stop, вкладки проверок, поиск по адресам, счётчики обзора, панель деталей и экспорт CSV/XLSX подключены к ядерным командам
#1347 (задача на GitHub)crawl-site --scan-outиscan-url-query; строка состояния показывает скорость, просканировано и осталось по данным самого ядра. При открытии экрана ничего не запускается, а временный результат удаляется по Clear, при следующем сканировании и при выходе из приложения. Пункты быстрого сканирования в меню открывают этот раздел. Значок «Unavailable in this core version» в верхней панели убран. «Сравнение» больше не открывается с ошибкой после чтения проекта: пустое сравнение — нейтральная подсказка выбрать два скана, а состояние «недоступно» показывается только при реальном сбое.
12 октября 2026 г.
8 добавлено10 изменено2 исправленоИсправленоРаботаетИсправлена совместимость конфигурации нативного скана при обновлениях и откатах.#1344
Сохранены существующий заголовок и отпечаток, новые эффективные опции хранятся в версионированном контексте, а при отсутствии контекста сохраняется прежнее поведение параметров отслеживания. При возобновлении проверяются все эффективные настройки; неподдерживаемые или несогласованные артефакты отклоняются.
#1344 (задача на GitHub)ИсправленоРаботаетИсправлено определение RDFa: относительные IRI и чужие хосты не дают разметку Schema.org…#1344
Исправлено определение сохранённой разметки RDFa: относительные IRI свойств и посторонние хосты больше не считаются разметкой Schema.org. Абсолютные IRI словарей и распознанные префиксы сохраняются, а тесты дедлайна поиска остаются ограниченными дешёвыми шаблонами фикстур.
#1344 (задача на GitHub)ИзмененоРаботаетКомпактные вкладки настроек проекта остаются в окне, дополнительные настройки — в меню#1315
переполнения…
Компактные вкладки настроек проекта остаются в окне, дополнительные настройки открываются через меню переполнения. Лишний выбор расписания скрывается, если доступен только основной сайт, а выбор между связанными сайтами сохраняется при любом размере окна. - Предпросмотр пользовательского User-Agent показывается, только если его значение доступно; название пресета не выдаётся за реально передаваемый заголовок. Заданные планировщиком границы задержек сохраняются. - Создание задач владельца пересчитывается после обновления проекта; совместимые запуски конкурентов, проверенные ядром, сохраняются при несвязанных ревизиях чек-листа. Подтверждение и проверка текущей ревизии по-прежнему обязательны для записи. - Проверка ботов отключена, пока не доступны сохранённые логи проекта; вызовы стандартной модели таблиц Qt поддержаны; сохранённые итоги проблем показываются отдельно от ограниченных выборок URL и неизмеренных проверок. - Встроенные шрифты регистрируются один раз на приложение, а не дублируются при каждой смене темы.
#1315 (задача на GitHub)ДобавленоРаботаетУправление учётными данными провайдеров только для записи через локальный канал stdin#1343
CLI, явный цикл согласия GSC OAuth…
Добавлено управление учётными данными провайдеров только для записи через локальный канал stdin CLI, явный жизненный цикл согласия на OAuth GSC и обнаружение ресурсов аккаунта только в режиме предпросмотра; выбор провайдера и запись учётных данных MCP остаются за явными решениями владельца. - Добавлены ограниченные находки URL Inspection в вывод SF, привязанный к проекту, за явной опцией
#1343 (задача на GitHub)--gsc-inspect, с локальным учётом квот по каждому свойству и сохраняемой историей проверок с allowlist. SF также объединяет измеренную историю URL из GSC, GA4, Metrika и Cloudflare без неявных вызовов провайдеров; зарегистрированные находки по каждому URL попадают в обычный поток проблем аудита, а отсутствующее или частичное покрытие названо явно. - Добавлены ежедневные агрегированные снимки Cloudflare по каждому URL, явный импорт Enterprise Logpull, импорт NDJSON Logpush, переданного вызывающей стороной, через локальное хранилище логов, а также опциональное чтение настроек ИИ, наборов правил редиректов и WAF и заданий Logpush только для чтения. Отдельно подтверждаемый захват Instant Logs, доступный по тарифу, использует короткую ограниченную сессию WebSocket и сохраняет только ограниченный локальный префикс; маршрут не трогает существующие сессии и сообщает о документированном истечении простоя Cloudflare, поскольку Edge API не предоставляет endpoint остановки. Потоки назначений Logpush остаются у клиента и не импортируются. - Добавлена явная текущая операция обратных ссылок Moz JSON-RPC при сохранении прежних метрик URL по умолчанию; неподтверждённые записи о расходах остаются null в журнальных отчётах. - Добавлен ограниченный читатель сводки артефактов PageSpeed, который проверяет владение и возвращает только разрешённые поля Lighthouse.ИзмененоРаботаетИменованные профили сканирования можно просматривать как проверенный JSON, выбирать через#1299
seo_crawl_siteи назначать по умолчанию для проекта…Именованные профили сканирования можно просматривать как проверенный JSON, выбирать через
#1299 (задача на GitHub)seo_crawl_siteи назначать проектам по умолчанию; переопределения сканирования проекта накладываются поверх. - Оценка прогресса сканирования считает время для текущего известного фронта и отделяет его от общей длительности; цели сканирования по умолчанию нормализуют параметрыutm_*иfbclid. - Активные нативные сканы проектов принимают разовые запросы паузы и остановки по идентификатору запуска и контрольной точке через существующий путь восстановления SQLite. - Basic/Digest-аутентификация, привязанная к хосту, и опциональное согласование ответов zstd используют ссылки на переменные окружения, явное подтверждение, аутентификацию только по HTTPS и бюджеты запросов. Результаты сканирования включают ограниченные оценки нагрузки; неизвестный размер диска сохраняется как null.ДобавленоРаботаетДобавлена сводка операционного статуса проекта: прогресс активных коллекторов, полнота#1291
последнего скана, состояние папок, открытые задачи основного проекта, последняя записанная активность агента и сохранённый размер папки сканов. Состояние соединения остаётся неизвестным без живого heartbeat.
#1291 (задача на GitHub)ДобавленоРаботаетДобавлен машиночитаемый контракт core-info с проверенными ревизией и временем сборки,#979
поддерживаемыми инструментами CLI и MCP и точной совместимостью с десктопом по ревизии; добавлены команда
#979 (задача на GitHub)doctorтолько для чтения и инструмент MCP для проверки локальных предпосылок.seohead --versionвыводит версию пакета. - Добавлены условные чтенияproject-observeиproject-activityс учётом ревизий и непрозрачными токенами; добавлены проверки новых версий с явного согласия и загрузка wheel и source с проверкой контрольной суммы, прогрессом, отменой и без автоматической установки.ДобавленоРаботаетДобавлены предварительные оценки платных стадий и история статусов по стадиям для#1298
проектов семантического ядра. - Поддержаны предпросмотр импорта CSV/XLSX с сопоставлением колонок, экспорт по области, постраничное чтение кластеров, аудируемый выбор посадочных страниц и локальные инсайты на основе доказательств.
#1298 (задача на GitHub)ДобавленоРаботаетДобавлены ограниченные действия страницы и пресеты для отрендеренных сканирований с#1302
включением на уровне проекта, сохранённые различия сырых и отрендеренных элементов…
Добавлены ограниченные действия страницы и пресеты для отрендеренных сканирований с включением на уровне проекта; сохранены различия сырых и отрендеренных элементов и сетевые сбои браузера; добавлены находки переполнения на мобильных, размера текста и размера цели по захваченной вёрстке. Добавлены скриншот первого экрана и явные метаданные представления DOM.
#1302 (задача на GitHub)ДобавленоРаботаетДобавлены точные состояния
checks_run,checks_skipped,checks_disabledи итоги#1296реестра в сохранённые доказательства сканов…
Добавлены точные состояния
#1296 (задача на GitHub)checks_run,checks_skipped,checks_disabledи итог реестра в сохранённые доказательства сканов проекта. Выполненные и пропущенные счётчики остаются непересекающимися, а отсутствующее покрытие аудита помечается как недоступное. - Сохранённые сканы показывают ограниченные окна статического и отрендеренного HTML с идентификацией скана и документа, хешами сырого тела и декодированного текста, а также страницы находок по точному URL через общие обработчики CLI и MCP. Детали URL включают ограниченное окно исходного HTML; недоступные и неоднозначные доказательства остаются явными. Сравнение тел поддерживает пары статический/отрендеренный, а также пары между сканами. - Статус скана показывает состояние целостности, затронутый скан, доступность контрольных точек и обнуляемые счётчики повреждений. Переносимые архивы проекта могут не содержать тел HTML, опускать тела старше 30 или 90 дней или сохранять только новейшие N распознанных сканов, оставляя таблицы доказательств нетронутыми.ИзмененоРаботаетРасширены запросы URL по сохранённым сканам: счётчики ссылок, фильтры по#1295
title/canonical/hreflang/sitemap и фасеты с учётом источника…
Расширены запросы URL по сохранённым сканам: счётчики сохранённых ссылок, фильтры по title/canonical/hreflang/sitemap и фасеты с учётом источника. Отсутствующие измерения ссылок, sitemap, hreflang или аудита остаются недоступными, а не отображаются как ноль. - Добавлены опциональные счётчики серьёзности и проверок по всему скану из сохранённой сводки аудита, включая явные состояния проверок: сработавшие, молчащие, пропущенные, отключённые и недоступные. - Индекс кратчайшей глубины клика, который можно перестроить, сохраняется при завершении захвата scan.v2 или офлайн-переанализа; старые файлы сканов продолжают вычислять глубину по сохранённому графу ссылок в пределах бюджета запроса. - Добавлены фильтры по типу и URL ресурсов, привязанные к исходному документу, счётчики вхождений и по типам, состояния сохранённых байтов и агрегаты блоков и весов в сохранённых доказательствах ресурсов; недоступные объявления и частичные веса загрузки остаются явными. - В scan.v2 сохраняются тайминги HTTPX: TCP/connect, TLS, ожидание заголовков ответа и загрузка тела, если транспорт выдаёт trace-события. DNS остаётся недоступным, потому что HTTPX не даёт отдельного события резолвера; его время может входить в connect. Добавлена офлайн-команда
#1295 (задача на GitHub)headers-analyzeдля сохранённых заголовков с редактированием и доказательств фаз. - Добавлено чтение дерева каталогов через CLI и MCP на временной агрегации SQLite с ограничениями глубины, числа потомков, узлов и байтов вывода. Прежнее чтение кратчайшего пути доступно черезscan-link-inspect --view path. - Добавленscan-link-inspect --view links --preset inlinks|broken_linksдля именованных представлений входящих внутренних ссылок и битых исходящих целей. - Финализация нативного scan.v2 и офлайн-переанализ теперь пытаются построить опциональную индексированную проекцию запросов URL, привязанную к источнику, для счётчиков и типов ресурсов страницы, флагов дублирующихся title, покрытия и нефильтрованных фасетов. Чтение принимает её только для завершённого скана с совпадающими UUID, ревизией доказательств, возможностями и стартовым URL; requeue инвалидирует публикацию. Старые сканы сохраняют резервное ограниченное чтение только для чтения, без миграции scan.v1. На синтетической фикстуре завершённого скана на 1 млн страниц с общим HTML и изображениями реальный производитель проекции завершился за 6,36 с при пиковом RSS 400,7 МБ. Медианы пяти прогонов: 5,23–43,38 мс для страниц с колонками ресурсов, 60,81 мс для фильтра изображений и 5,38 мс для всех фасетов, в рамках бюджетов 200 и 300 мс; 100 строк изображений совпали точно. Это проверяет производительность запросов на синтетических данных, а не живое сканирование 1 млн URL. Фасеты входящих ссылок и sitemap остались явно недоступными, поэтому ответ фасетов частичный.ИзмененоРаботаетЧек-лист проекта v4 получил исполнителей, критерии приёмки, ссылки на находки и методы,#1294
границы…
Чек-лист проекта v4 содержит исполнителей, критерии приёмки, ссылки на находки и методы, ограниченные лимиты URL конкурентов и комментарии к задачам с атрибуцией, которые только добавляются, при этом прежние форматы покрытия продолжают читаться. - Принятие цели из входящих создаёт задачу чек-листа с устойчивым идентификатором и исходной целью в описании; принятие по-прежнему не запускает и не закрывает задачу. - Представления задач и отчётов показывают честные состояния измерения затронутых URL для каждой задачи и KPI пользовательских задач; счётчики остаются недоступными, если сохранённые доказательства не перечисляют затронутые URL.
#1294 (задача на GitHub)ИзмененоРаботаетОтчёты проекта в Markdown, DOCX и XLSX включают счётчики пользовательских задач,#1297
назначения и приёмку…
Отчёты проекта в Markdown, DOCX и XLSX включают счётчики пользовательских задач, поля назначения и приёмки, а также обнуляемые доказательства по затронутым URL с состоянием измерения.
#1297 (задача на GitHub)ДобавленоРаботаетДобавлены метаданные категорий и привязки к проекту с постраничной выборкой по смещению в#1312
каталог инструментов MCP, а также пакетная проверка URL для явных списков или страниц сохранённых сканов. - Добавлена автоматическая оценка качества изображений по SSIM, явное удаление EXIF и отчёты об оптимизации изображений из сохранённых сканов; добавлен вывод CSV для WordPress Redirection с локальным анализом цепочек и петель. - Флаги прежней глубины и задержки сканирования показываются в справке, при этом сохраняется их совместимое поведение.
#1312 (задача на GitHub)ДобавленоРаботаетДобавлено ограниченное чтение потоков compare.v2 с проверкой целостности, сортировкой и#1300
фильтрацией по URL; сформированы резюме в Markdown и карточки «до/после» по точному URL, где отсутствующие наблюдения остаются как «не перепроверено». - Сохранённая история URL расширена фактами страниц и дельтами соседних сканов; недоступные и отсутствующие наблюдения остаются несопоставимыми. - Контрольные точки сравнения и снимки прогресса сохраняются для возобновления по точному входу; проверенные завершённые пакеты переиспользуются как попадания в кэш; добавлены срезы изменений по основному сегменту и сохранённые доказательства кодов ответа внешних ссылок.
#1300 (задача на GitHub)ИзмененоРаботаетЧитатель сохранённых структурированных данных по точному URL расширен ограниченными#1304
JSON-LD, Microdata, RDFa, доказательствами языка, происхождением источника и офлайн-валидацией Schema.org.
Читатель сохранённых структурированных данных по точному URL расширен ограниченными JSON-LD, Microdata, RDFa, доказательствами языка, происхождением источника и локальной офлайн-валидацией Schema.org.
#1304 (задача на GitHub)ИзмененоРаботаетПоиск по сохранённому контенту теперь выдаёт ограниченные вхождения с символьными#1301
смещениями в исходном тексте, номерами строк с единицы и навигацией по совпадениям внутри документа…
Поиск по сохранённому контенту теперь выдаёт ограниченные вхождения с символьными смещениями в исходном тексте, номерами строк с единицы, навигацией по совпадениям внутри каждого документа и опциональными редактированными окнами из шести строк. Фильтр по точному URL выполняется до ранжирования документов SQLite. Полное число совпадений остаётся видимым, когда лимит в 10 000 смещений или 64 КиБ на запись обрезает возвращённые вхождения, и покрытие помечается как частичное. Регулярные выражения недоступны, если нельзя обеспечить дедлайн по реальному времени; недоступные тела остаются неизвестными, а не отсутствующими. - Пакеты индексированного поиска ограничены 512 МиБ; при достижении лимита публикуется явно неполный пакет с измеренным покрытием и лимитом байтов. - Добавлен офлайн-маршрут образца пользовательского извлечения для HTML, переданного вызывающей стороной. Его необязательный URL — только метка и не запускает загрузку; живая загрузка URL остаётся решением владельца.
#1301 (задача на GitHub)ИзмененоРаботаетИмпорт строк CSV правок сниппетов в непримененные задачи проверки, измерение типографики#1010
и выдержки по запросам из выбранных сканов…
Строки CSV правок сниппетов импортируются как непримененные задачи проверки, локальная типографика измеряется по профилю, заданному вызывающей стороной, а из явно выбранных сохранённых сканов добавляются выдержки по запросам с происхождением документа. Порог поисковой системы или утверждение о рендеринге не выводятся.
#1010 (задача на GitHub)ИзмененоРаботаетНативные сохранённые сканирования сравнивают сохранённые тела ответов с ограниченным#1013
набором распознаваемых семейств Content-Type; недоступные, слишком большие и неоднозначные тела остаются явно неизмеренными.
#1013 (задача на GitHub)ИзмененоРаботаетНативный анализ изображений сообщает об отсутствующих и некорректных размерах и о#1303
неинформативном или испорченном пустом alt…
Нативный анализ изображений сообщает об отсутствующих и некорректных объявлениях размеров, а также о неинформативном или испорченном пустом alt, сохраняя корректный декоративный
#1303 (задача на GitHub)alt="". Буквально отсутствующие атрибуты alt остаются находками с именем ARIA; видимым декоративным изображениям всё равно нужны размеры. - Находки по изображениям сохраняют область source/target/status, причину, документ и ограниченные порядковые позиции. Отсутствующие тела сохраняют известные положительные факты о числе страниц, не выдумывая URL изображения или ответ ресурса. Ошибки ответа изображения и пороги байтов сохраняют статус и причину. - Выбор изображений определяет исходные страницы после переоткрытия. Доказательства ресурсов называют сохранённые строки загрузки и объявлений рядом с исходными документами. Идентичность нативного изображения включает исходную страницу и область, намеренно не допуская схлопывания между страницами, и мигрирует старые отпечатки нативных изображений. Старые находки без исходной страницы сохраняют прежнюю идентичность; повторяющиеся элементы сохраняют точные счётчики и ограниченные выборки мест. - Синтетический магазин сохраняет исходные дефекты и 15 контрольных образцов и добавляет случаи с информативным пустым alt и отсутствующим размером на существующих товарах, не меняя счётчики сканирования.
11 октября 2026 г.
16 измененоИзмененоРаботаетПолный набор инструментов запускается один раз на Python 3.15 вместо матрицы старых
версий, с сохранением четырёх проверенных групп тестов и суммарного покрытия…
Полный набор инструментов запускается один раз на Python 3.15 вместо матрицы старых версий: сохранены четыре проверенные группы тестов и суммарное покрытие. Для CI и сборок релиза используется одна и та же стабильная версия Python.
ИзмененоРаботаетКонсолидация сохранённых проверок аудита и улучшения нативного десктопа.
Настройки бюджета ресурсов сохранены без изменения замороженного заголовка скана; безопасный офлайн-переанализ и возобновление сохранены; компоненты настроек проекта, токены темы и встроенные шрифты стали общими. Приватные исходные дизайн-материалы удалены из распространяемого дерева. - Перепроверки ремедиации привязаны к проверенной эффективной политике ассетов с сохранением исходного заголовка скана и исходных байтов.
ИзмененоРаботаетВкладки «Schedule» и «Crawl» в настройках проекта перестроены на общих нативных#1323
компонентах canvas, офлайн-шрифтах Roboto и Material Symbols, с одноколоночным макетом от 800 px. - Интерфейс приложения полностью на английском; существующие контракты команд и документов расписания сохранены, а отображаются только данные расписания, подтверждённые ядром. - Идентичности и псевдонимы рабочих пространств сохраняются, пока открыты настройки проекта; повторные сохранения блокируются, пока ядро отвечает.
#1323 (задача на GitHub)ИзмененоРаботаетНастройки проекта на десктопе получили вкладку «Schedule» (дни недели, дни месяца, окно#1322
запуска, часовой пояс…
Настройки проекта на десктопе получают вкладку «Schedule» (дни недели, дни месяца, окно запуска, часовой пояс, конкуренты) и вкладку «Crawl» (режим сканирования, пресет User-Agent или своя строка, пауза между запросами, бюджет URL, SpiderHeadBot или свой user agent); обе читают и пишут проект через ядро, а обзор проекта показывает следующий и последний запланированный запуск. Режим --tray запускает запланированные ядром сканы и не даёт Mac уснуть, пока идёт скан.
#1322 (задача на GitHub)ИзмененоРаботаетНативные аудиты теперь показывают render-blocking разметку head из полных сохранённых#1303
HTML без изменения замороженной схемы scan.v1. Отсутствующие, неполные и ограниченные бюджетом тела остаются недоступными. Существующее обнаружение ресурсов head и вход пользовательского извлечения SF переиспользуются. - Добавлены настраиваемые бюджеты байтов для наблюдаемой навигации и отдельных ресурсов, сигналы доставки кэша и шрифтов, эвристики минификации и устаревших скриптов, а также точные дубликаты скриптов на одной странице из сохранённых доказательств scan.v2. Незагруженные данные и неполные данные времени выполнения остаются явными; адаптивные объявления не суммируются как вес времени выполнения. Нижние границы только по HTML, скалярные счётчики покрытия, образцы шрифтов и сводки источников остаются явными и ограниченными. - Собираются ограниченные точные данные покрытия JS/CSS Chromium при запрошенных рендерах; сохраняются сводки использования в UTF-16, а также находки по размерам изображений при рендеринге, которые читаются после переоткрытия или офлайн-переанализа. Неподдерживаемые движки и отсутствующие измерения не становятся чистым результатом. - Принимается ограниченный совпадающий JSON Lighthouse по каждому URL для обнаружения LCP, деревьев зависимостей, виновников сдвига макета, доставки изображений, принудительного reflow и выполнения скриптов, с происхождением захвата и хешами входа. Процесс Lighthouse, платный провайдер или вывод полевых CWV не добавляются. Реестр, покрытие SF и сгенерированная справочная документация обновлены. - Дополнительные пороги ассетов хранятся вне замороженного заголовка нативного скана, а их точные значения — в проверенном версионированном контексте запуска. При возобновлении эти значения сравниваются отдельно, а офлайн-переанализ восстанавливает их из сохранённых доказательств; старые облегчённые читатели по-прежнему видят неизменную форму конфигурации заголовка.
#1303 (задача на GitHub)ИзмененоРаботаетСтатические доказательства AMP и доступности, привязанные к документу, сохраняются в#1304
существующих строках контекста скана без изменения схемы scan.v1…
Статические доказательства AMP и доступности, привязанные к документу, сохраняются в существующих строках контекста скана без изменения замороженной схемы SQL
#1304 (задача на GitHub)scan.v1. Структурные находки AMP проверяют исходный doctype, head и body, кодировку UTF-8, viewport, runtime-скрипт и объявления шаблона; парные цели AMP без корневого маркера AMP выделяются отдельно. Полные правила валидатора AMP остаются недоступными до решения по лицензии. - Запущены находки доступности: язык документа, подписи полей форм, альтернативные тексты изображений, скачки заголовков и главный landmark. Находки сохраняют ограниченные примеры и полные счётчики вхождений. Вычисляемый контраст и отрендеренные правила axe-core остаются неизмеренными. - Валидируются Schema.org Microdata и распространённые субъекты и свойства RDFa по встроенному словарю и существующим правилам rich results. Сохранённые по URL ошибки, предупреждения и отсутствующие обязательные свойства становятся нативными находками. Неподдерживаемые конструкции RDFa помечаются как явное частичное доказательство, а не как чистый результат валидации. - Разобранные деревья JSON-LD отдаются черезscan-structured-blocksвместе с источником, позицией и ошибками синтаксиса по каждому блоку; широкие деревья свойств ограничиваются, а лимит показывается. Последний документ для запрошенного URL и представления читается без изменения его скана. - Частичные и недоступные структурированные доказательства сохраняются, не скрывая подтверждённые соседние ошибки. Поддерживаемые идентичности JSON-LD разрешаются по той же базе документа, что и HTML-разметка, с сохранением исходного JSON; скалярные и пустые блоки JSON не принимаются как валидные графы, а нормализованный выбор живых тегов JSON-LD общий для парсера и отдаваемых проекций.ИзмененоРаботаетСырые атрибуты canonical и пагинации сохраняются как версионированный контекст документа#1305
без изменения замороженного SQL скана. Ссылки canonical с неподдерживаемыми атрибутами hreflang, lang, media или type, некорректные аннотации и объявления на другой хост или протокол теперь дают находки, привязанные к доказательствам; неизвестные корректные ключевые слова отношений остаются неклассифицированными. - Ограниченные проверки целевых URL того же хоста распространены на пагинацию, сохраняются измеренные наблюдения noindex и canonical. Нативные цепочки canonical и находки noindex для canonical и hreflang могут использовать проверки; устаревшие проверки только по статусу остаются читаемыми и не измеряют директивы HTML. - Непрозрачные нативные цепочки пагинации оцениваются на явные взаимно противоречивые next и prev с сохранением правил нумерации и шага и именованных неоценённых состояний. Выбор сохранённых URL находок, включая сгруппированных участников, выполняется через scan-url-query с временными таблицами SQLite и потоковыми доказательствами audit.v2. - Неизвестные токены отношений с Unicode и знаками пунктуации остаются неклассифицированными; эквивалентные IDN и порт по умолчанию в authority canonical нормализуются, а точные пути целей пагинации сохраняются. Нечитаемые смешанные токены страниц остаются неоценёнными; дефект пагинации магазина распознаётся, даже если на первой странице нет номера в URL. - Фикстура магазина отдаёт объявленные аннотации next и prev, чтобы эталон пагинации D41 действительно отдавался и мог проверяться нативным захватом.
#1305 (задача на GitHub)ИзмененоРаботаетСерверные логи теперь хранят точные дисковые итоги по IP ботов вместо ограниченной#1311
выборки, с записями по IP, визитами и фильтрами подсетей…
Серверные логи теперь хранят точные дисковые итоги по IP ботов вместо ограниченной выборки: ограниченные записи по IP, визиты, последний визит и фильтры подсетей. Явная DNS-проверка проверяет каждый выбранный IP отдельно, фиксирует доказательства PTR и прямой записи, поддерживает IPv6 и сохраняет исходы недоступности и дедлайна как непроверенные. Локальные кэши истекают через час; чтение никогда не запускает DNS. - Добавлены локальный импорт логов проекта, постраничная сводка, доказательства ботов и команды соединения с нативным сканом через общие обработчики CLI и MCP. Отдельные артефакты логов сохраняют разбиение по датам и покрытие источника с происхождением, не меняя замороженные схемы сканов. Отсутствующие или неполные доказательства не дают выводов об отсутствии. Экраны логов на десктопе остаются отдельной задачей презентации.
#1311 (задача на GitHub)ИзмененоРаботаетНативные аудиты группируют битые внутренние ссылки по наблюдаемой цели с доказательствами#1306
источника и анкора; цепочки и петли редиректов фиксируются по каждому хопу…
Нативные сохранённые аудиты группируют битые внутренние ссылки по наблюдаемой цели с доказательствами источника и анкора, записывают цепочки и петли редиректов с статусами по каждому хопу, различают внутренний поиск по пути и пустые анкоры и показывают зафиксированные исходы без ответа для внешних ссылок. Проверки согласованности sitemap и robots используют сохранённые данные о членстве и ответах без повторной загрузки; отсутствующие и частичные доказательства остаются явными. - Добавлен ограниченный граф ссылок сохранённых сканов с фильтрами по позиции, разделу и локальному окружению, агрегацией по разделам и изменениями рёбер между сканами. Офлайн-переанализ дозаполняет позиции через возобновляемые производные пакеты и показывает неклассифицированные доказательства в проверке ссылок и статусе скана, сохраняя замороженную схему scan.v1. - Добавлена локальная генерация XML-sitemap из канонических индексируемых страниц с кодом 200 из сохранённого каталога с наблюдаемым lastmod, исключениями, разбиением по протоколам, индексом sitemap и опциональным image sitemap. CLI и MCP используют одну реализацию; публикация вывода требует новой локальной папки и никогда не деплоит файлы. - Цели обнаружения, зафиксированные при захвате, сохраняются, когда последующая обработка sitemap или seed добавляет URL в сохранённый каталог. Объяснённые неразрешённые и исключённые доказательства остаются неизменными, а заявленные известные цели и несовпадения непустой идентичности остаются недействительными. - Sitemap изображений исключает известные ответы ресурсов не-200, даже если ресурс не сохранялся как страница сканирования, и помечает неизмеренные ответы изображений как частичное покрытие.
#1306 (задача на GitHub)ИзмененоРаботаетВызовы Google DataForSEO в продакшене проходят проверку до создания клиента,#1310
офлайн-котировки по ценам провайдера…
Вызовы Google DataForSEO в продакшене проверяются до создания клиента; офлайн-котировки строятся по переданным ценам провайдера; учитываются глубина SERP и оплата поисковых операторов, а известные лимиты USD на вызов проверяются до передачи запроса. Расширены ограниченные операции с индексом обратных ссылок; отсутствующие расходы и некорректная форма ответа записываются в журнал как неуверенные чеки. Лимиты валюты по проекту и месяцу остаются ожидающим решением владельца. - Явные данные обратных ссылок и импорт сливаются в приватные локальные снимки истории с полными наблюдениями токенов rel, анкорами, referring domains, фильтрами и прозрачными сигналами проверки спама. Добавлены маршруты CLI и MCP для профиля и экспорта проверенного disavow без автоматической отправки. - Добавлены уведомления о смешанных токенах rel и раскрытии спонсорской разметки исходящих ссылок из сохранённых нативных доказательств: недоступный контекст сохраняется, для полностью неразобранных популяций HTML счётчики равны null, а классы sponsored, ugc и nofollow попадают в отчёты и проверки донора, без изменения замороженной схемы сохранённого скана.
#1310 (задача на GitHub)ИзмененоРаботаетНативные проверки DOM и дубликатов читают выбранный сохранённый документ каждой страницы#1307
по точному URL с проверенным происхождением ответа и тела. Отключённое хранение, отсутствующие, некорректные или превышающие бюджет тела остаются явными пропусками; частичные находки несут покрытие. Точные хеши области контента и ограниченные находки SimHash/LSH сохраняются в нативном аудите без требования каталога HTML SF. Адаптивные по порогу полосы LSH сохраняют полноту квалифицирующих пар и уменьшают широкие корзины кандидатов; исчерпание бюджета близкого анализа не отбрасывает находки по точным хешам. - SF-аудиты опционально выполняют семантическое сходство и проверку title и H1 относительно сохранённого тела, с явно заданным локальным адаптером или объявленными эмбеддингами. Модель или провайдер автоматически не выбираются. Идентичность адаптера, хеши источников, оценки, лимиты и пропуски сопровождают кандидатов на проверку; семантическое сходство не утверждает дублирования контента, релевантности запросу или каннибализации. Два строки покрытия семантики SF остаются пробелами, пока не выбран и не проверен реальный адаптер. Авторизация внешнего провайдера требует литерального булева
#1307 (задача на GitHub)true; строковые или числовые значения не разрешают вызов эмбеддинга.ИзмененоРаботаетСсылки входящих принимают идентификаторы целей (
inbox:<uuid>), чтобы заметка могла#1314ссылаться на касающуюся её цель. - Пункты чек-листа, которые ни разу не запускались и являются ручными, получают состояние
#1314 (задача на GitHub)not_runвместоreview; вreviewостаётся только попытка, ожидающая решения. - Модель чтения Issues (доказательстваobserveпо находкам) показывает счётчики по проверкам (by_check) иnext_offsetпосле первых 20 находок;findings_pageлистает остальные.ИзмененоРаботаетЗапланированные сканы проектов (#1322, ядро):
schedule.jsonв каждой папке проекта#1322хранит независимое расписание сайта…
Запланированные сканы проектов (#1322, ядро):
#1322 (задача на GitHub)schedule.jsonв папке каждого проекта хранит независимое расписание этого сайта (дни недели и/или числа месяца, окно запуска в часовом поясе сайта, включение и выключение, режим сканированияspider,sitemapилиlist, лимиты URL и запросов на запуск, пауза вежливости, user agent и состояние возобновления среза относительно проекта). Проект-владелец может включать связанных конкурентов, у каждого из которых свой ритм и политика сканирования. Настройки редактируются черезschedule-setиseo_schedule_setсexpected_revision;schedule-showпоказывает состояние срока у основного сайта и связанных конкурентов и следующий запуск.schedule-run-due— точка входа без интерфейса: запускает только независимо созревшие сканы, удерживает блокировки в пределах процесса до окончания запуска, фиксирует состояние отмены до повторного выброса и записывает результаты или пересечения конкурентов в журнал каждого затронутого проекта.schedule-installиschedule-uninstallзаписывают или удаляют plist launchd, строку cron или команду Task Scheduler только при явном вызове. - Пресеты user agent для сканирования:spiderhead,googlebot,googlebot-desktop,googlebot-smartphone,bingbot,yandexbot,yandexmobilebot,baiduspider,duckduckbot,applebot,gptbot,claudebot,perplexitybot, а также настольные и мобильные браузеры — или одна своя строка. По умолчанию теперьSpiderHeadBot/<version> (+https://github.com/PavloSEO/spiderhead), а сопоставление группы robots.txt использует ту же идентичность. Сайты, которые соответствовали прежней группеSEOHEAD-Toolsв robots.txt, должны называтьSpiderHeadBotв своих правилах.ИзмененоРаботает
workflow-startтребует только принятой цели владельца: достаточно--goal-idили#1314context.goal_id…
#1314 (задача на GitHub)workflow-startтребует только принятой цели владельца: достаточно--goal-id(илиcontext.goal_id). По умолчанию промпт —skill:workflow/full-audit-v1, а задача чек-листа — та, что создана при принятии цели (custom:goal-<entry>). Отказы называют команду владельца, которая устраняет недостающую связь. Опции описаны вseohead workflow-start --help. - Популяции чек-листа принимают частичные объекты: обязательны толькоkindиsource, остальные ключи по умолчанию не заданы. Отказанная популяция называет отсутствующие или неизвестные ключи. - Нативные сканы проектов при отсутствии sitemap в robots.txt берут/sitemap.xmlс origin. Отсутствующий запасной вариант фиксируется как неполный, но не прерывает сканирование.ИзмененоРаботаетРабочие пространства конкурентов сохраняют URL в том виде, в каком он введён:#1314
сканирование начинается с URL с
www…Рабочие пространства конкурентов сохраняют URL в том виде, в каком он введён: сканирование конкурента начинается с его URL с
#1314 (задача на GitHub)www, а не с голого хоста, и сканирование URL конкурента больше не отмечает пункты чек-листа владельца; результат записывается только в собственном рабочем пространстве конкурента. Открытие проекта с повреждённым рабочим пространством конкурента помечает его недоступным вместо ошибки.ИзмененоРаботаетПокрытие чек-листа проекта теперь привязывается к потоковым отчётам audit.v2:
report-build --projectиaudit-workflow --action reportприкладывают снимок чек-листа к выводу xlsx, docx, csv, md и PDF-обзору вместо сборки непривязанного отчёта. Скан, остановленный бюджетом URL (stopped_by_budget), принимается как последний аудированный скан проекта, а в его отчёте указан ограниченный охват.report-build --inputпринимает ключformat.report-build --project --format jsonдля потокового аудита отклоняется с объяснением, потому что JSON записывается дословно и не может нести снимок чек-листа.
Дорожная карта
108 открытыхОткрытые майлстоуны на GitHub. Каждая строка — открытая задача: это план, ещё не выпущено.
Основы десктопа
Сначала рабочий десктоп: блокеры, размер 800×600, мёртвые вкладки, честные состояния (волна 1 плана десктопа)
ДобавленоЗапланированоDesktop: проверка владельцем на реальном проекте (визуал, сканы, проблемы, экспорт,#1358
инструменты)
#1358 (задача на GitHub)- ИсправленоЗапланированоDesktop: мёртвые вкладки, неактивные действия и экраны-заглушки#1347 (задача на GitHub)
ДобавленоЗапланированоWindows: падают нативный краулинг, журнал проекта и сборка Desktop; Desktop плодит пустые#1345
окна и непригоден на 4K
#1345 (задача на GitHub)
Паритет десктопа
UX десктопа на уровне привычных краулеров: вкладки, колонки под фильтр, детализация обзора, сохранение раскладки (эпик #1522)
- ДобавленоЗапланированоВкладки деталей работают с выделением нескольких строк#1498 (задача на GitHub)
- ДобавленоЗапланированоЕдиное состояние активности для всех окон и элементов управления#1496 (задача на GitHub)
- ДобавленоЗапланированоПомощник визуального извлечения с подсказками селекторов#1461 (задача на GitHub)
Движок краулинга
Вежливость и политики robots, повторы, бюджеты, обнаружение URL, масштаб хранения, жизненный цикл скана (эпик #1520)
- ДобавленоЗапланированоСобирать каноникал и пагинацию из HTTP-заголовка Link с указанием источника объявления#1517 (задача на GitHub)
- ДобавленоЗапланированоУправление идущим краулингом: сужение области и добавление URL на лету#1485 (задача на GitHub)
- ДобавленоЗапланированоОпциональный краулинг маршрутов с идентификатором фрагмента#1482 (задача на GitHub)
- ДобавленоЗапланированоАвтоматический лимит параллельных отрисовываемых страниц по доступной памяти#1480 (задача на GitHub)
- ДобавленоЗапланированоВключать содержимое shadow DOM и iframe в снимок рендеринга#1477 (задача на GitHub)
- ДобавленоЗапланированоСобирать сообщения консоли браузера для каждого отрисованного URL#1475 (задача на GitHub)
- ДобавленоЗапланированоЗащита от нехватки свободного места на диске для хранилища сканов#1474 (задача на GitHub)
- ДобавленоЗапланированоРезервный режим совместимости для серверов со старым TLS#1473 (задача на GitHub)
- ДобавленоЗапланированоКлассифицированная причина сетевого сбоя для каждого URL#1472 (задача на GitHub)
- ДобавленоЗапланированоЗаписывать источник обнаружения каждого просканированного URL#1471 (задача на GitHub)
- ДобавленоЗапланированоРазрешать относительные ссылки относительно базового URL документа#1470 (задача на GitHub)
- ДобавленоЗапланированоСтабильный порядок обхода для воспроизводимых краулингов#1469 (задача на GitHub)
- ДобавленоЗапланированоСтруктурная нормализация URL перед дедупликацией при краулинге#1466 (задача на GitHub)
- ДобавленоЗапланированоЗагружать robots.txt не более одного раза на origin при параллельной работе#1465 (задача на GitHub)
- ДобавленоЗапланированоУчитывать Retry-After и сбавлять темп при ответах с троттлингом#1463 (задача на GitHub)
ДобавленоЗапланированоРасширенные краулинг-бюджеты: глубина папок, на поддомен, на уровень глубины, на шаблон#1445
пути, максимум ссылок на страницу
#1445 (задача на GitHub)ДобавленоЗапланированоПараметры генерации sitemap: priority, changefreq, PDF, изображения с CDN, файлы по#1444
сегментам
#1444 (задача на GitHub)- ДобавленоЗапланированоДоверенные пользовательские CA-сертификаты для краулируемого трафика#1442 (задача на GitHub)
- ДобавленоЗапланированоОбнаружение по целям аннотаций (canonical, hreflang, AMP, meta refresh, iframe)#1436 (задача на GitHub)
- ДобавленоЗапланированоКраулинг и аудит медиаэлементов (video, audio, source)#1435 (задача на GitHub)
- ДобавленоЗапланированоОбнаружение и отчёт о внутренних ссылках, недоступных для краулинга#1434 (задача на GitHub)
- ДобавленоЗапланированоЛокальный сбор Lighthouse для выборки отрисованных URL#1430 (задача на GitHub)
ДобавленоЗапланированоcontrol/rate-and-load: отделять 5xx, вызванные скоростью, от 403/429 защиты от ботов на#1366
шаге «прежде чем винить сайт»
#1366 (задача на GitHub)- ДобавленоЗапланированоrobots-check сообщает «no robots.txt (crawl allowed)», когда robots.txt отдаёт 403 от WAF#1364 (задача на GitHub)
ДобавленоЗапланированоHTTP-клиент получает 403 на каждый запрос к Shopify-витрине за Cloudflare, которая#1363
отвечает 200 на curl
#1363 (задача на GitHub)- ДобавленоЗапланированоLive crawl speed control: change rate and threads during a running scan#1360 (задача на GitHub)
ДобавленоЗапланированоCore: шероховатости, найденные при подключении реальных проектов (конкуренты, логи,#1359
лимиты краулинга, архив)
#1359 (задача на GitHub)
Анализ и поля данных
Читабельность, векторы и семантика, поля по каждому URL, покрытие проверок, сводки (эпик #1521)
- ДобавленоЗапланированоОбъединение нескольких табличных экспортов в одну книгу#1528 (задача на GitHub)
- ДобавленоЗапланированоНаходки по доступности с выбором уровня WCAG и таксономией серьёзности по влиянию#1526 (задача на GitHub)
- ДобавленоЗапланированоЗаписывать атрибут SameSite для каждого наблюдаемого cookie#1519 (задача на GitHub)
- ДобавленоЗапланированоМногодвижковое пользовательское извлечение со статусом валидации#1513 (задача на GitHub)
- ДобавленоЗапланированоБалл внутренних ссылок как опциональная метрика после краулинга#1510 (задача на GitHub)
- ДобавленоЗапланированоПанель рекомендаций по каждой находке с копированием и внешними ссылками#1507 (задача на GitHub)
- ДобавленоЗапланированоДельта находок между двумя сканами с подсветкой улучшений#1506 (задача на GitHub)
- ДобавленоЗапланированоАгрегация использования каждого изображения по страницам#1457 (задача на GitHub)
- ДобавленоЗапланированоПоказывать подходящее правило robots.txt для каждого заблокированного URL#1456 (задача на GitHub)
- ДобавленоЗапланированоИзвлечение аннотаций hreflang из HTTP-заголовков Link и XML-sitemap#1455 (задача на GitHub)
- ДобавленоЗапланированоПроцент схожести пар почти-дублей и подсветка различий#1454 (задача на GitHub)
- ДобавленоЗапланированоАудит инвентаря cookie со сводкой по собственным и сторонним#1453 (задача на GitHub)
- ДобавленоЗапланированоОтслеживать дублирующиеся и множественные meta keywords по страницам#1452 (задача на GitHub)
- ДобавленоЗапланированоСобирать CSS-фоновые изображения как данные об изображениях#1451 (задача на GitHub)
- ДобавленоЗапланированоНаходки по цепочкам редиректов, заканчивающимся клиентской или серверной ошибкой#1450 (задача на GitHub)
- ДобавленоЗапланированоНастраиваемая выборка анализа для оценки дублей и проблем#1449 (задача на GitHub)
- ДобавленоЗапланированоАнализ частотности N-грамм по просканированному контенту#1431 (задача на GitHub)
- ДобавленоЗапланированоСсылки и текст, видимые только после рендеринга, как полноценные находки#1429 (задача на GitHub)
- ДобавленоЗапланированоДобавить проверки битых и закрытых в robots.txt внешних JS- и CSS-файлов#1427 (задача на GitHub)
- ДобавленоЗапланированоДобавить проверку слишком большого числа JS- и CSS-файлов на странице#1426 (задача на GitHub)
- ДобавленоЗапланированоДобавить проверку несоответствия языка в hreflang и html lang#1425 (задача на GitHub)
- ДобавленоЗапланированоДобавить в сканы находки по вариантам главной с www и по http#1423 (задача на GitHub)
ДобавленоЗапланированоДобавить TLS-проверку: срок сертификата, несовпадение имени хоста, версия протокола,#1418
слабые шифры
#1418 (задача на GitHub)- ДобавленоЗапланированоДобавить проверку не-HTML ресурсов, на которые ведут обычные ссылки#1417 (задача на GitHub)
- ДобавленоЗапланированоДобавить проверку страниц с единственной внутренней входящей ссылкой#1416 (задача на GitHub)
- ДобавленоЗапланированоСохранять внешние ссылки с rel и добавить EXTERNAL_NOFOLLOW#1415 (задача на GitHub)
ИсправленоЗапланированоЗаголовки безопасности и HSTS оцениваются только по финальному ответу; промежуточные#1414
редиректы и хост www не проверяются никогда
#1414 (задача на GitHub)ИсправленоЗапланированоПравила расширенных результатов SoftwareApplication слишком мягкие; проверить, что ошибки#1413
структурированных данных главной выводятся
#1413 (задача на GitHub)- ИсправленоЗапланированоLOW_TEXT_RATIO срабатывает почти на каждой странице; перекалибровать метрику и порог#1412 (задача на GitHub)
- ИсправленоЗапланированоСгруппированные находки показывают счётчик 1 и отсутствуют в поиске находок по URL#1411 (задача на GitHub)
ДобавленоЗапланированоsite-audit выдаёт находки уровня страницы для ответа с ошибкой вместо пометки «страница#1365
не проверена»
#1365 (задача на GitHub)
Проекты и сценарии
Сценарии владельца сайта: задачи, выгрузки, отчёты по расписанию и их доставка (эпик #1314)
- ДобавленоЗапланированоДоставка отчётов запланированного мониторинга по email#1531 (задача на GitHub)
Ребрендинг
Переименование seohead → spiderhead: CLI, пакет, окружение, документация (#1523)
- ДобавленоЗапланированоПереименовать CLI-бинарник, пакет и префикс переменных окружения с seohead на spiderhead#1523 (задача на GitHub)
Интерфейсы CLI и MCP
Понятные ошибки, настоящая справка, ограниченный вывод при чтении, транспорты MCP (эпики #1410 #1421)
- ДобавленоЗапланированоMCP-сервер как полноценный режим CLI с транспортами stdio и streamable HTTP#1525 (задача на GitHub)
- ИсправленоЗапланированоПоказывать реальную подсправку для 'seohead sf' вместо заглушки с передачей аргументов#1406 (задача на GitHub)
ИИ-слой
Цели промптов для каждого SEO-элемента поверх seo_ai_column, без привязки к провайдеру (#1524)
- ДобавленоЗапланированоИИ-анализ страниц с настраиваемыми целями промптов по данным краулинга#1524 (задача на GitHub)
Качество кода
Разделение «божественных» файлов на модули и направление зависимостей (#1514 #1515)
- ДобавленоЗапланированоНаправление зависимостей: убрать инверсии импорта из ядра в функциональные модули#1515 (задача на GitHub)
- ДобавленоЗапланированоРазделить чрезмерно крупные модули адаптеров и движков на связные части#1514 (задача на 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.
- ДобавленоЗапланированоOwn command name with a one-command install (pipx/brew) for the CLI#1557 (задача на GitHub)
- ДобавленоЗапланированоShip native installers: DMG (macOS), Linux (AppImage/deb), Windows installer#1556 (задача на GitHub)
3.1.0
Первый тегированный релиз после переименования из SEOHEAD Tools11 октября 2026 г.455 записей · Первый тегированный релиз после переименования из SEOHEAD Tools138 добавлено275 изменено42 исправлено
11 октября 2026 г.
5 добавлено54 изменено2 исправленоИзмененоРаботаетВкладки «Schedule» и «Crawl» в настройках проекта перестроены на общих нативных#1323
компонентах canvas, офлайн-шрифтах Roboto и Material Symbols, с одноколоночным макетом от 800 px.
#1323 (задача на GitHub)ИзмененоРаботаетВесь интерфейс приложения на английском; существующие контракты команд расписания и#1323
документов сохранены, отображаются только данные расписания из ядра…
Весь интерфейс приложения на английском; существующие контракты команд расписания и документов сохранены, а отображаются только данные расписания, подтверждённые ядром.
#1323 (задача на GitHub)ИзмененоРаботаетИдентичности и псевдонимы рабочих пространств сохраняются, пока открыты настройки#1323
проекта; повторные сохранения блокируются, пока ядро отвечает.
#1323 (задача на GitHub)ИзмененоРаботаетНастройки проекта на десктопе получили вкладку «Schedule» (дни недели, дни месяца, окно#1322
запуска, часовой пояс…
Настройки проекта на десктопе получают вкладку «Schedule» (дни недели, дни месяца, окно запуска, часовой пояс, конкуренты) и вкладку «Crawl» (режим сканирования, пресет User-Agent или своя строка, пауза между запросами, бюджет URL, SpiderHeadBot или свой user agent); обе читают и пишут проект через ядро, а обзор проекта показывает следующий и последний запланированный запуск. Режим --tray запускает запланированные ядром сканы и не даёт Mac уснуть, пока идёт скан.
#1322 (задача на GitHub)ИзмененоРаботаетПлановые сканирования проектов (#1322, ядро):
schedule.jsonв папке проекта хранит#1322расписание: дни недели и/или числа месяца, временное окно в часовом поясе сайта, включение и выключение, конкурентов, режим сканирования
#1322 (задача на GitHub)spider/sitemap/list, бюджеты URL и запросов на один запуск, паузу между запросами и режим срезов, который продолжает предыдущее неполное сканирование. Редактируется черезschedule-set/seo_schedule_setсexpected_revision;schedule-showпоказывает последний запуск и ближайшее окно.schedule-run-due— точка входа без интерфейса: запускает только назначенные сканирования, отказывается от перекрытия по аренде и записывает каждое решение в журнал проекта.schedule-installиschedule-uninstallзаписывают или удаляют plist для launchd, строку cron или команду Task Scheduler только при явном вызове.ИзмененоРаботаетUser-agent для сканирования (#1322): пресеты (
spiderhead,googlebot,#1322
#1322 (задача на GitHub)googlebot-desktop,googlebot-smartphone,bingbot,yandexbot,yandexmobilebot,baiduspider,duckduckbot,applebot,gptbot,claudebot,perplexitybot, а также десктопные и мобильные браузеры) или одна пользовательская строка. По умолчанию теперьSpiderHeadBot/<version> (+https://github.com/PavloSEO/spiderhead), а сопоставление групп в robots.txt использует тот же идентификатор. Сайтам, которые попадали в прежнюю группуSEOHEAD-Toolsв robots.txt, нужно указыватьSpiderHeadBotв своих правилах.ИзмененоРаботаетСохранённое сканирование проекта теперь отмечает автоматические пункты чек-листа, которые#1314
оно измерило.
Каждый включённый пункт проверки получает один из трёх результатов:
#1314 (задача на GitHub)succeeded, если сохранённый аудит выполнил проверку, а скан служит доказательством;unavailable, если сканирование пропустило или отключило её, и причина сканирования сохраняется; илиunmeasured, если аудит вообще не упоминает проверку. Неизмеренный пункт сохраняет прежнюю запись и называется по имени вchecklist_evidence, поэтому никогда не засчитывается как 0. Сканирование, которое завершилось ошибкой или было прервано, помечает свои автоматические проверки какfailedс причиной сбоя. Тот же путь записи теперь обслуживает потокprepare, который раньше вёл собственную копию цикла. Проект с непроинициализированным чек-листом пропускается с указанной причиной.ИзмененоРаботаетРабочие пространства конкурентов сохраняют URL в том виде, в каком его ввели:#1314
сканирование конкурента стартует с его
#1314 (задача на GitHub)www-URL, а не с голого хоста. Сканирование URL конкурента больше не отмечает пункты чек-листа владельца; результат записывается только в рабочее пространство конкурента. Открытие проекта с повреждённым рабочим пространством конкурента помечает этого конкурента как недоступного, а не приводит к ошибке.ИзмененоРаботаетКандидатов в конкуренты можно добавлять, просматривать и удалять из CLI#1314
(
#1314 (задача на GitHub)project-competitors-add,project-competitors-list,project-competitors-remove) и через соответствующие MCP-инструментыseo_project_competitors_*. Каждый кандидат сохраняет URL как введён, включая хост сwww; варианты с www и без него считаются одним сайтом при проверке дублей. Конкурент с хостомwwwбольше не ломает подготовку и не приводит к сбоюproject-observe.ИзмененоРаботает
--max-urlsтеперь бюджет страниц сканирования: явный бюджет страниц заполняет#1314незаданные бюджеты запросов…
#1314 (задача на GitHub)--max-urlsтеперь задаёт бюджет страниц сканирования: явно заданный бюджет страниц заполняет незаданные бюджеты запросов и времени (3 запроса и 2 секунды на страницу), поэтому сканирования на 50–300 страниц проходят безapprove_large_crawl. Бюджеты выше пороговых значений проекта по-прежнему отклоняются.ИзмененоРаботаетНамеренная остановка по бюджету URL сохраняется как завершённый захват с
finish_reason#1314
#1314 (задача на GitHub)stopped_by_budgetи временемfinished_at, а не какinterruptedбез времени завершения. Его URL в очереди остаются для продолжения.ИзмененоРаботаетURL конкурентов сохраняют хост как введён (например,
www.остаётся), а не хранятся без#1314ИзмененоРаботаетDesktop добавляет сайты конкурентов из буфера обмена или по одному через ядро, задаёт#1314
лимит URL на сайт…
Desktop добавляет сайты конкурентов из буфера обмена или по одному через ядро, задаёт лимит URL на каждый сайт и запускает их сканирование параллельно. Сайт конкурента считается просканированным только после завершённого сохранённого скана.
#1314 (задача на GitHub)ИзмененоРаботаетНативные сканирования измеряют HSTS, смешанный контент и структурированные данные по#1314
собственным сохранённым доказательствам, поэтому отсутствующий или устаревший экспорт SF больше не сообщает, что их нет.
#1314 (задача на GitHub)duplicate-checkпомечает запуск с нулём сравниваемых пар как неизмеренный. Общесайтовые находки шаблона (одинаковый заголовок блока, низкая доля текста) объединены в одну находку с количеством страниц (#1314).ИзмененоРаботаетПринятие цели владельца добавляет только задачу чек-листа этой цели.#1314
Весь встроенный каталог больше не сверяется с
#1314 (задача на GitHub)coverage.json: встроенные строки добавляются по требованию, когда до них дотрагиваются.ИзмененоРаботаетЗанятый чек-лист называет живого держателя (например, работающее нативное сканирование и#1314
его pid), а не считает блокировку остатком. Блокировка записывает pid своего писателя; блокировка без живого держателя по-прежнему отображается как остаток.
#1314 (задача на GitHub)ИзмененоРаботаетЗапуск рабочего процесса, заблокированный упавшим, недоступным, пропущенным или#1314
прерванным шагом, всё ещё можно возобновить, а более поздний ожидающий шаг может быть зафиксирован за шагом, не давшим успеха. Шаги по-прежнему фиксируются в зарегистрированном порядке, а прерванный запуск отказывается принимать дальнейшие шаги.
#1314 (задача на GitHub)ИзмененоРаботаетОбзор, записанный агентом, больше не делает ручной пункт или результат полностью#1314
подтверждённым владельцем.
Пункт остаётся в ожидании подтверждения владельца или проверки не агентом.
#1314 (задача на GitHub)ИзмененоРаботаетСсылки из входящих принимают id целей (
inbox:<uuid>), поэтому заметка может ссылаться#1314на цель, которой она касается.
#1314 (задача на GitHub)ИзмененоРаботаетРучные пункты чек-листа, которые ни разу не запускались, показывают состояние
not_run,#1314а не
#1314 (задача на GitHub)review. В состоянииreviewостаётся только попытка, ожидающая решения.ИзмененоРаботаетМодель чтения Issues (доказательства
observeдля находок) отдаёт счётчики по проверкам#1314(
#1314 (задача на GitHub)by_check) иnext_offsetпосле первых 20 находок.findings_pageлистает остальные.ИзмененоРаботаетНативные проверки сканирования (#1314): размер изображения (
IMG_OVER_KB) теперь#1314измеряется по собственным загрузкам изображений сканирования, а статус sitemap (
#1314 (задача на GitHub)SITEMAP_URL_4XX_5XX,SITEMAP_URL_3XX,SITEMAP_URL_NON_INDEXABLE) по собственной загрузке каждого URL из sitemap. URL из sitemap, который сканирование так и не запросило, считается неизмеренным, а не чистым.IMG_MISSING_ALT,IMG_MISSING_DIMENSIONSиHREFLANG_ERRORв нативном скане сообщают, что сканирование не измеряет их так, как их определяет экспорт SF, вместо того чтобы вести к фильтру SF. Отсутствие hreflang и данные о смешанном контенте в нативном скане отмечаются как не измеренные нативным сканированием, а не как отсутствующий экспорт.ИзмененоРаботаетЖурнал проекта (#1314): каждое событие проекта теперь также записывается одним пунктом в#1314
log.md…
Журнал проекта (#1314): каждое событие проекта теперь также записывается одним пунктом в
#1314 (задача на GitHub)log.md, а ядро автоматически добавляет записи о завершённых сканированиях (scans), построенных отчётах проекта и попытках чек-листа (agent). Записи попадают вevents.jsonlи читаются черезproject-event-page. Автоматические хуки никогда не валят сканирование, отчёт или шаг чек-листа, которые описывают.project-event-appendиseo_project_event_appendсохраняют интерфейс и получают строку вlog.md.ИзмененоРаботаетНативное сканирование теперь сохраняет заголовки безопасности, которые читают проверки#1314
(
#1314 (задача на GitHub)Strict-Transport-Security,Content-Security-Policy,X-Frame-Options,X-Content-Type-Options,Referrer-Policy,Permissions-Policy). Раньше их отбрасывали при захвате, и сайт с HSTS помечался как не имеющий его. Заголовки Set-Cookie сохраняют только свои флаги (secure,httponly,samesite=), но никогда не имя или значение cookie. Заголовок безопасности, отправленный больше одного раза на одной странице, отмечается какDUPLICATE_SECURITY_HEADER.ИзмененоРаботает
workflow-startтребует только принятую цель владельца:--goal-id(или#1314context.goal_id)…
#1314 (задача на GitHub)workflow-startтребует только принятую цель владельца: достаточно--goal-id(илиcontext.goal_id). Зарегистрированный промпт по умолчанию —skill:workflow/full-audit-v1, а пункт чек-листа — тот, что принимает созданную цель (custom:goal-<entry>). Отказы называют команду владельца, которая устраняет недостающую связь. Опции описаны вseohead workflow-start --help.ИзмененоРаботаетПопуляции чек-листа принимают частичные объекты: обязательны только
kindиsource, а…#1314Популяции чек-листа принимают частичные объекты: обязательны только
#1314 (задача на GitHub)kindиsource, остальные ключи по умолчанию не заданы. Отклонённая популяция называет свои недостающие или неизвестные ключи.ИзмененоРаботаетНативные сканирования проектов переходят на
/sitemap.xmlисточника, если robots.txt не#1314объявляет sitemap. Отсутствие такого запасного варианта фиксируется как неполное, но не прерывает сканирование.
#1314 (задача на GitHub)ИзмененоРаботаетСерверные логи теперь хранят точные дисковые итоги по IP ботов вместо ограниченной#1311
выборки, с ограниченными записями по каждому IP, визитами, последним визитом и фильтрами по подсетям. Явная DNS-проверка проверяет каждый выбранный IP отдельно, записывает доказательства PTR и прямой записи, поддерживает IPv6 и сохраняет результаты «недоступно» и «истёк срок» как непроверенные. Локальные кэши устаревают через час; чтение никогда не запускает DNS.
#1311 (задача на GitHub)ДобавленоРаботаетДобавлены импорт локальных логов проекта, постраничная сводка, доказательства ботов и#1311
соединение с нативным сканированием…
Добавлены импорт локальных логов проекта, постраничная сводка, доказательства ботов и команды соединения с нативным сканированием через общие обработчики CLI/MCP. Отдельные артефакты логов сохраняют разбиение по датам и покрытие источников с происхождением, не меняя замороженные схемы сканирований. При отсутствии или неполноте доказательств выводы об отсутствии не делаются. Экранные разделы логов в Desktop остаются отдельным следующим этапом.
#1311 (задача на GitHub)ИзмененоРаботаетЗакрыть производственные вызовы Google DataForSEO до создания клиента, показывать#1310
офлайн-расценки по переданным ценам провайдера…
Производственные вызовы Google DataForSEO закрыты до создания клиента: офлайн-расценки считаются по переданным ценам провайдера, учитываются глубина SERP и платные операторы поиска, а известные лимиты в USD за вызов соблюдаются до передачи данных. Расширены ограниченные операции с индексом обратных ссылок; отсутствующие расходы и некорректная форма ответа записываются в журнал как неопределённые квитанции. Лимиты в валюте по проекту и месяцу ждут решения владельца.
#1310 (задача на GitHub)ИзмененоРаботаетОбъединять явные данные об источниках и импорте обратных ссылок в приватные локальные#1310
снимки истории с полными наблюдениями rel-токенов, анкорами, ссылающимися доменами, фильтрами и прозрачными сигналами проверки спама. Добавлены маршруты CLI/MCP для профиля и проверенного экспорта disavow без автоматической отправки.
#1310 (задача на GitHub)ДобавленоРаботаетДобавить уведомления о проверке смешанных rel-токенов и исходящих sponsored-пометок из#1310
сохранённых нативных данных…
Добавлены уведомления о проверке смешанных rel-токенов и исходящих sponsored-пометок из сохранённых нативных данных: сохраняется недоступный контекст, для полностью неразобранных HTML-популяций ставятся null-счётчики, а классы sponsored/ugc/nofollow выводятся в отчётах и проверках донорских ссылок. Замороженная схема сохранённого скана при этом не меняется.
#1310 (задача на GitHub)ИзмененоРаботаетНативные проверки DOM и дублей теперь читают выбранный сохранённый документ каждой#1307
страницы по точному URL, с проверенной связью ответа и тела. Отключённое хранение, отсутствующие, некорректные или превышающие бюджет тела остаются явными исключениями; частичные находки несут данные о покрытии. Точные хэши содержимого области и ограниченные находки SimHash/LSH сохраняются в нативном аудите без необходимости в HTML-каталоге SF. Пороговые полосы LSH с адаптивным порогом сохраняют полноту квалифицирующих пар и сокращают широкие кандидатные корзины; исчерпание бюджета near-анализа не отбрасывает находки по точным хэшам.
#1307 (задача на GitHub)ИзмененоРаботаетАудиты SF опционально запускают семантическое сходство и проверку title/H1 против#1307
сохранённого тела страницы, с явно переданным локальным адаптером или заявленными эмбеддингами. Модель или провайдер никогда не выбираются автоматически. Идентичность адаптера, хэши источников, оценки, лимиты и пропуски сопровождают кандидатов на проверку. Семантическое сходство не утверждает дублирование контента, релевантность запросу или каннибализацию. Две строки покрытия семантики SF остаются пробелами, пока не выбран и не проверен реальный адаптер. Для внешнего провайдера разрешение требует литерального булева
#1307 (задача на GitHub)true: строки и числа, которые лишь считаются истинными, никогда не разрешают вызов эмбеддинга.ИзмененоРаботаетНативные сохранённые аудиты теперь группируют битые внутренние ссылки по наблюдаемой цели#1306
с доказательствами источника и анкора, фиксируют цепочки редиректов и петли с кодами статуса по каждому переходу, различают внутренний поиск по пути и пустые анкоры и показывают зафиксированные внешние исходы «нет ответа». Находки по согласованности sitemap и robots используют сохранённое членство и данные ответа без повторных живых запросов; отсутствующие и частичные данные остаются явными.
#1306 (задача на GitHub)ДобавленоРаботаетДобавлен ограниченный граф ссылок сохранённых сканирований с фильтрами по позиции,#1306
разделу и локальной окрестности, агрегацией по разделам и изменениями рёбер между сканированиями. Офлайн-переанализ заполняет позиции возобновляемыми производными пакетами и сообщает о неклассифицированных данных в проверке ссылок и статусе сканирования, сохраняя замороженную схему scan.v1.
#1306 (задача на GitHub)ДобавленоРаботаетДобавлена локальная генерация XML-sitemap из канонических индексируемых сохранённых#1306
страниц с ответом 200 с наблюдаемым lastmod, исключениями, разбиением по протоколу, индексом sitemap и необязательным sitemap изображений. CLI и MCP используют одну и ту же реализацию; публикация вывода требует свежего локального каталога и никогда не разворачивает файлы.
#1306 (задача на GitHub)ИзмененоРаботаетСохранять цели обнаружения, отсутствовавшие на момент захвата, когда последующая#1306
обработка sitemap или seed добавляет URL в сохранённый каталог…
Сохраняются цели обнаружения, отсутствовавшие на момент захвата, когда последующая обработка sitemap или seed добавляет URL в сохранённый каталог. Объяснённые нерешённые и исключённые данные остаются неизменными, а заявленные известные цели и ненулевые расхождения идентичности остаются недействительными.
#1306 (задача на GitHub)ИзмененоРаботаетГенерация image sitemap исключает известные ответы ресурсов с кодом не 200, даже если#1306
ресурс не сохранялся как просканированная страница, и помечает неизмеренные ответы изображений как частичное покрытие.
#1306 (задача на GitHub)ИзмененоРаботаетСохранять исходные атрибуты canonical и пагинации как версионированный контекст документа#1305
без…
Исходные атрибуты canonical и пагинации сохраняются как версионированный контекст документа без изменения замороженного SQL сканирования. Canonical-ссылки с неподдерживаемыми атрибутами hreflang/lang/media/type, некорректные аннотации и объявления между хостами или протоколами теперь дают находки, привязанные к доказательствам. Неизвестные корректные ключевые слова отношений остаются неклассифицированными.
#1305 (задача на GitHub)ИзмененоРаботаетРасширить ограниченные пробы целей на том же хосте на пагинацию и сохранять измеренные#1305
наблюдения noindex/canonical…
Пробы целей на том же хосте расширены на пагинацию, а измеренные наблюдения noindex/canonical сохраняются. Нативные цепочки canonical и находки noindex для canonical/hreflang могут использовать пробы. Устаревшие пробы только по статусу остаются читаемыми и не измеренными для HTML-директив.
#1305 (задача на GitHub)ИзмененоРаботаетОценивать непрозрачные нативные цепочки пагинации на явные взаимные противоречия#1305
next/prev…
Непрозрачные нативные цепочки пагинации оцениваются на явные взаимные противоречия next/prev. Нумерованные и шаговые правила сохраняются, а неоценённые состояния называются явно. Выбор URL сохранённых находок, включая членов групп, выполняется через scan-url-query с временными таблицами SQLite и потоковым чтением доказательств audit.v2.
#1305 (задача на GitHub)ИсправленоРаботаетОставлять неизвестные Unicode- и пунктуационные relation-токены неклассифицированными,#1305
нормализовать…
Неизвестные Unicode- и пунктуационные relation-токены остаются неклассифицированными, эквивалентные IDN и порты по умолчанию в canonical-адресах нормализуются, а точные пути целей пагинации сохраняются. Нечитаемые смешанные токены страниц остаются неоценёнными. Дефект пагинации магазина выявляется, даже если у первой страницы в URL нет номера.
#1305 (задача на GitHub)ИзмененоРаботаетОтрисовать объявленные в фикстуре магазина аннотации next/prev, чтобы его эталон#1305
пагинации D41…
Отрисовать объявленные в фикстуре магазина аннотации next/prev, чтобы его эталонные данные пагинации D41 действительно отдавались сервером и могли проверяться нативным захватом.
#1305 (задача на GitHub)ИзмененоРаботаетСохранять привязанные к документу статические данные AMP и доступности в существующем#1304
контексте скана…
Привязанные к документу статические данные AMP и доступности сохраняются в существующих строках контекста скана, не меняя замороженную схему SQL
#1304 (задача на GitHub)scan.v1. Структурные находки AMP проверяют исходный doctype, head/body, кодировку UTF-8, viewport, скрипт среды выполнения и объявления шаблонного кода. Парные цели AMP без корневого маркера AMP выделяются отдельно. Полные правила валидатора AMP остаются недоступными до решения по лицензии.ИзмененоРаботаетНачало проверок доступности: язык документа, подписи полей формы, альтернативы#1304
изображений…
Начинаются проверки доступности: язык документа, подписи полей формы, альтернативные тексты изображений, пропуски уровней заголовков и главный landmark. Находки сохраняют ограниченные примеры и полное число вхождений. Вычисляемый контраст и отрисованные правила axe-core остаются неизмеренными.
#1304 (задача на GitHub)ИзмененоРаботаетПроверять Schema.org Microdata и распространённые субъекты/свойства RDFa встроенным#1304
словарём…
Microdata Schema.org и распространённые субъекты и свойства RDFa проверяются встроенным словарём и существующими правилами rich-результатов. Сохранённые по каждому URL ошибки, предупреждения и отсутствующие обязательные свойства становятся нативными находками. Неподдерживаемые конструкции RDFa выводятся как явное частичное доказательство, а не как чистый результат проверки.
#1304 (задача на GitHub)ИзмененоРаботаетОтдавать разобранные деревья JSON-LD вместе с ошибками источника, позиции и синтаксиса по#1304
блокам в…
Отдавать разобранные деревья JSON-LD вместе с ошибками источника, позиции и синтаксиса по каждому блоку в
#1304 (задача на GitHub)scan-structured-blocks. Широкие деревья свойств ограничиваются, а их лимит показывается. Последний документ для запрошенного URL и представления читается без изменения его скана.ИзмененоРаботаетСохранять частичные и недоступные структурированные данные, не скрывая подтверждённых#1304
ошибок соседних элементов.
Поддерживаемые идентификаторы JSON-LD разрешаются относительно той же базы документа, что и HTML-разметка, с сохранением исходного JSON. Скалярные и пустые блоки JSON не принимаются как валидные графы, а нормализованный выбор живых JSON-LD-тегов общий для парсера и отдаваемых проекций.
#1304 (задача на GitHub)ИзмененоРаботаетНативные аудиты теперь показывают блокирующую рендер разметку head из полного#1303
сохранённого HTML без изменения замороженной схемы scan.v1. Отсутствующие, неполные и ограниченные бюджетом тела остаются недоступными. Существующее обнаружение ресурсов head и вход пользовательского извлечения SF переиспользуются.
#1303 (задача на GitHub)ДобавленоРаботаетДобавить настраиваемые бюджеты нативной наблюдаемой навигации и байтов отдельных ресурсов…#1303
Добавлены настраиваемые бюджеты нативной наблюдаемой навигации и байтов отдельных ресурсов, сигналы доставки кэша и шрифтов, эвристики минификации и устаревших скриптов, а также точные дубли скриптов на одной странице по сохранённым доказательствам scan.v2. Непосчитанные данные и неполные полезные нагрузки среды выполнения остаются явными. Адаптивные объявления не суммируются как вес во время выполнения. Нижние границы только по HTML, скалярные счётчики покрытия, выборки шрифтов и сводки источников остаются явными и ограниченными.
#1303 (задача на GitHub)ИзмененоРаботаетСобирать ограниченное точное покрытие JS/CSS в Chromium при запрошенных рендерах,#1303
сохранять сводки использования UTF-16…
При запрошенных рендерах собирается ограниченное точное покрытие JS/CSS в Chromium, сохраняются сводки использования UTF-16 и находки по размерам отрисованных изображений. Их чтение выполняется после повторного открытия или офлайн-переанализа. Неподдерживаемые движки и отсутствующие измерения не становятся чистыми результатами.
#1303 (задача на GitHub)ИзмененоРаботаетПринимать ограниченный совпадающий JSON Lighthouse по каждому URL для обнаружения LCP,#1303
деревьев зависимостей…
Принимается ограниченный совпадающий JSON Lighthouse по каждому URL для находок: обнаружение LCP, деревья зависимостей, виновники сдвигов макета, доставка изображений, принудительный reflow и выполнение скриптов, с происхождением захвата и хэшами входных данных. Процесс Lighthouse, платный провайдер и вывод полевых CWV не добавляются. Обновляются реестр, покрытие SF и сгенерированная справочная документация.
#1303 (задача на GitHub)ИсправленоРаботаетХранить дополнительные пороги ресурсов вне замороженного заголовка нативного скана и#1303
сохранять их точные значения…
Дополнительные пороги ресурсов хранятся вне замороженного заголовка нативного скана, а их точные значения — в проверенном версионированном контексте запуска. Возобновление сравнивает эти значения отдельно, а офлайн-переанализ восстанавливает их из сохранённых доказательств. Более старые облегчённые читатели по-прежнему могут смотреть неизменённую форму конфигурации заголовка.
#1303 (задача на GitHub)ИзмененоРаботает
recordчек-листа теперь принимает успешно выполненную автоматическую проверку, еслисохранённый скан — потоковый audit.v2. Раньше запись падала с
'NoneType' object is not subscriptable, потому что аудит хранится в companion-файле, а не в устаревшей таблице скана. Принимаемые формы записей описаны вseohead project checklist-record --help, в схеме MCPseo_project_checklist_recordи вdocs/INPUTS.md.ИзмененоРаботаетПрогонять полный набор инструментов один раз на Python 3.15 вместо матрицы старых версий…
Полный набор инструментов прогоняется один раз на Python 3.15 вместо матрицы старых версий: сохраняются четыре проверенные группы тестов и объединённое покрытие. Для начальной загрузки CI и сборок релиза используется одна и та же стабильная версия Python.
ИзмененоРаботаетРабочий список Desktop читает каждую страницу чек-листа (по 100 за запрос), а не первые
50 строк. В разделе Issues каждая основная проверка называется по реестру, а не выводится как «Other check».
ИзмененоРаботаетDesktop Work читает каждую страницу чек-листа, но показывает панель задач проекта по
одной странице за раз, поэтому чек-лист любого размера больше не падает с ошибкой «at most 100 rows». Desktop открывает скан, который оставляет полный аудит (самый большой полный скан), если владелец не выбрал его сам. Обнаружение в ядре также проверяет собственное окружение интерпретатора Desktop (
sys.prefix) раньше PATH.ИзмененоРаботаетОбъединить проверки сохранённого аудита и нативные улучшения desktop.
Настройки бюджета ресурсов сохраняются без изменения замороженного заголовка скана. Безопасный офлайн-переанализ и возобновление сохраняются, а нативные компоненты настроек проекта, токены темы и встроенные шрифты становятся общими. Приватные дизайн-материалы удалены из распространяемого дерева.
ИзмененоРаботаетПривязывать перепроверки исправлений к проверенной эффективной политике ассетов, сохраняя
исходный…
Перепроверки исправлений привязываются к проверенной эффективной политике ассетов, при этом исходный заголовок скана и байты источника сохраняются.
ИзмененоРаботаетПокрытие чек-листа проекта теперь привязывает потоковые отчёты audit.v2:
report-build --projectи
audit-workflow --action reportприкладывают снимок чек-листа к выводу xlsx, docx, csv, md и PDF-обзора вместо построения непривязанного отчёта. Скан, остановленный бюджетом URL (stopped_by_budget), принимается как последний аудированный скан проекта, а его отчёт указывает ограниченный охват.report-build --inputпринимает ключformat.report-build --project --format jsonдля потокового аудита отклоняется с объяснением, потому что JSON пишется дословно и не может содержать снимок чек-листа.
10 октября 2026 г.
16 добавлено51 измененоИзмененоРаботаетМонитор сканирования в Desktop следует дизайн-доске ScanRun: реальный процент по#1203
счётчикам fetched/found, полоса прогресса 10 px, лимит частоты коллектора и честная заглушка графика скорости 120 px (история частоты в ядре отслеживается в #1203).
#1203 (задача на GitHub)ИзмененоРаботает
check_sampleвseohead/checks/custom_extract.pyзапускает извлекатели CSS, XPath и#1059regex по одному сохранённому HTML-документу без скана и сетевого запроса. Каждый результат несёт свои значения и
#1059 (задача на GitHub)reasonдля пустого исхода (no_match,empty_htmlилиbudget_exceeded), поэтому пустой ответ никогда не подаётся как чистый результат (#1059). Это только вызов ядра. CLI- или MCP-инструмент пока не зарегистрирован, а получение живого URL намеренно не включено.ИзмененоРаботаетПроверка последовательности пагинации (
PAGINATION_SEQUENCE_ERROR) теперь оценивает#1057серии с шагом: когда один шаг покрывает большую часть шагов серии…
Проверка последовательности пагинации (
#1057 (задача на GitHub)PAGINATION_SEQUENCE_ERROR) теперь оценивает серии с шагом: если один шаг покрывает большую часть шагов серии, сообщается о нарушении этого шага (?page=1,3,5,8нарушается между 5 и 8). Нерегулярные схемы смещений и ненумерованные серии остаются неоценёнными и называются пропущенными.ДобавленоРаботаетНовая проверка сканирования
INTERNAL_NOFOLLOW_OUTLINKS(notice): называет каждую#1052страницу-источник, которая содержит внутренние исходящие ссылки nofollow…
Новая проверка сканирования
#1052 (задача на GitHub)INTERNAL_NOFOLLOW_OUTLINKS(notice): называет каждую страницу-источник, на которой есть внутренние исходящие ссылки сnofollow, указывает их количество и ограниченную выборку целевых адресов. Она закрывает пробел на уровне страниц для строки «Internal Nofollow Outlinks» из Screaming Frog, которая до этого былаpartial. Проверка работает на нативных сканированиях и пропускается по имени в запусках «только экспорт» и по списку URL.ИзмененоРаботаетПарсер читает
<link rel="alternate">с атрибутом media, но безhreflang(отдельный#1051мобильный URL)…
Парсер записывает объявления
#1051 (задача на GitHub)<link rel="alternate">с атрибутом media, но безhreflang(отдельный мобильный URL), вparse_htmlкакmobile_alternates(#1051). Проверка «Mobile Alternate Link» из SF по-прежнему остаётся пробелом: проверка, которая сравнивает канонический URL мобильной версии, ещё не написана.ДобавленоРаботаетДобавлена проверка
HREFLANG_UNLINKED_TARGET(warning): целевой адрес#1050hreflang-альтернативы, на который не ведёт ни одна обычная гиперссылка…
Добавлена проверка
#1050 (задача на GitHub)HREFLANG_UNLINKED_TARGET(warning): сообщается о целевом адресе hreflang-альтернативы, на который не ведёт ни одна обычная гиперссылка в сканировании. Теперь покрыт отчёт Screaming Frog «Unlinked Hreflang URLs». Проверка читает экспорт All Hreflang и колонку Internal:All Inlinks так же, какUNLINKED_CANONICAL. Ссылка на саму страницу не учитывается, а при частичном сканировании результат не выводится. Реестр вырос с 182 до 183 проверок.ИзмененоРаботаетРазмер изображений на отрисованных маршрутах: render-check теперь фиксирует собственный#1049
размер каждого изображения в пикселях относительно его отрисованного блока и коэффициента плотности пикселей устройства (
#1049 (задача на GitHub)image_sizing: данные о завышенных и увеличенных изображениях). Это только доказательства: идентификатора проверки в SF-analyzer пока нет, поэтому «Incorrectly Sized Images» переходит из статуса «пробел» в «частично» (#1049).ИзмененоРаботаетSemantically Similar: статус остаётся
gap, а в примечании теперь назван блокер.#1041Команда и инструмент MCP для семантического сходства есть, но адаптер эмбеддингов не поставляется, а запуск SF пока не вызывает этот модуль (#1041).
#1041 (задача на GitHub)ДобавленоРаботаетДобавлена проверка
INTERNAL_LINK_SPONSORED_UGC(notice): ссылка в пределах сайта с#1040rel="sponsored" или rel="ugc"…
Добавлена проверка
#1040 (задача на GitHub)INTERNAL_LINK_SPONSORED_UGC(notice): ссылка в пределах того же сайта сrel="sponsored"илиrel="ugc"выводится с полным набором значений rel. Для неё нуженlink_attributes.capture, как и для других проверок по rel. Без него она помечается как не измеренная.ДобавленоРаботаетДобавлено ядро генерации XML-карты сайта из сохранённого сканирования:
select_indexable#1039оставляет только…
Добавлено ядро генерации XML-карты сайта из сохранённого сканирования.
#1039 (задача на GitHub)select_indexableоставляет только HTML-страницы со статусом 200, которые ссылаются каноническим тегом на себя, не закрытыnoindexи не заблокированы в robots.txt, и указывает причину для каждого исключённого URL.render_sitemapsзаписывает<urlset>либо набор файлов плюс<sitemapindex>при разбиении по 50 000 URL или 52 428 800 байт на файл. Вывод в CLI и MCP — следующим шагом.ДобавленоРаботаетДобавлены
cloudflare-traffic(CLI) иseo_cloudflare_traffic(MCP): источник только#1026для чтения на базе Cloudflare GraphQL Analytics для анализатора логов, когда серверных логов нет (#1026, #1009). Он возвращает боты × URL × коды статусов × статус кэша по дням в формате
#1026 (задача на GitHub)log-analyzeи помеченsource: cloudflare-aggregated, потому что это агрегированные данные граничной сети, а не сырые логи (IP-адресов клиентов нет, поэтому обратная DNS-проверка невозможна). Дни, которые упираются в лимит 10 000 строк на страницу, делятся на временные окна. Вызов учитывается в журнале расходов как бесплатный провайдер. Токен берётся изCLOUDFLARE_API_TOKENилиSEOHEAD_CLOUDFLARE_TOKEN_FILEи никогда не выводится.ИзмененоРаботаетВнутренний оценщик находок Search Console, пока не подключённый к отчётам:#1025
#1025 (задача на GitHub)seohead/checks/search_console_findings.pyсоединяет страницы сканирования с нормализованным документом GSC и оценивает GSC_ORPHAN, NO_SEARCH_DATA и NON_INDEXABLE_WITH_SEARCH_DATA. Проверка пропускается с указанием причины, если сканирование частичное, окно данных неполное, коллекция выборочная или обрезанная либо доказательства не переданы. Пропущенная проверка никогда не отмечается как пройденная.ИзмененоРаботает
crawl-enrichвыводит четыре находки веб-аналитики из офлайн-CSV с URL в качестве ключа…#1024
#1024 (задача на GitHub)crawl-enrichвыводит четыре находки веб-аналитики из офлайн-CSV, где ключом служит URL: аналитические орфан-URL, индексируемые страницы без данных аналитики, неиндексируемые страницы с визитами и показатель отказов выше 70%. Нужные колонки выбираются параметрами--visits-columnи--bounce-column. Отсутствующая колонка отклоняется с указанием имени, нечитаемые значения подсчитываются и никогда не считаются нулём, а аналитические орфан-URL не выводятся при частичном сканировании. Получение данных Метрики и GA4 по каждому URL в реальном времени пока не включено (#990, #984).ИзмененоРаботаетКарта покрытия проблем SF: четыре проблемы веб-аналитики (Orphan URLs, Bounce Rate…#1024
Карта покрытия проблем SF теперь относит четыре проблемы веб-аналитики (Orphan URLs, Bounce Rate Above 70%, No GA Data, Non-Indexable with GA Data) к тем, которые находит
#1024 (задача на GitHub)crawl-enrichиз офлайн-CSV, а не к вне зоны охвата.sf runпока их не выводит.ИзмененоРаботаетЯдро лабораторного покрытия для неиспользуемых CSS и JavaScript (#1023, срез 1): чистый#1023
анализатор принимает данные
#1023 (задача на GitHub)page.coverageиз Playwright и сообщает по каждому ресурсу число неиспользуемых символов. Если ресурс в основном не используется и при этом большой, выводится находка. Сбор покрытия с отрисованной страницы — следующий срез.ИзмененоРаботаетПроверки пар AMP (#1020):
AMP_NON_200,AMP_MISSING_CANONICAL,#1020
#1020 (задача на GitHub)AMP_MISSING_RETURN_LINK,AMP_NON_INDEXABLE_CANONICALиAMP_INDEXABLEчитают AMP-цель, которую десктопная страница объявляет через<link rel="amphtml">. Оцениваются только AMP-страницы, которые сканирование захватило; незахваченная цель — пропуск с указанием причины. Нативное сканирование теперь записывает разрешённую цель в колонкуAMP HTML. Остальные десять правил SF для AMP по-прежнему отклонены.ДобавленоРаботаетДобавлена
HTML_OVER_2MB— абсолютный потолок 2 МБ для HTML-документа, отдельный от…#1019Добавлена проверка
#1019 (задача на GitHub)HTML_OVER_2MB: абсолютный потолок 2 МБ для HTML-документа, отдельный от относительного к медианеLARGE_HTML. Теперь «HTML Document Over 2MB» из Screaming Frog соответствует ей, а не правилу 200 КБ.ДобавленоРаботаетДобавлено уведомление
URL_HAS_PARAMETERSв аудит сканирования: внутренняя#1018HTML-страница, URL которой содержит параметры…
Добавлено уведомление
#1018 (задача на GitHub)URL_HAS_PARAMETERSв аудит сканирования: внутренняя HTML-страница, чей URL содержит параметры запроса, выводится независимо от канонического тега.URL_HAS_PARAMSсохраняет более узкий смысл — проверку страниц без канонического тега (#1018).ИзмененоРаботаетДирективы robots (#1017): устаревшие
noodpиnoydirв meta robots илиX-Robots-Tag#1017теперь дают уведомления
#1017 (задача на GitHub)NOODPиNOYDIRв аудите SF; раньше они числились вне зоны охвата.none(noindex+nofollow) покрыт регрессионными тестами как для путиX-Robots-Tag, так и для meta.ДобавленоРаботаетНовая проверка сканирования
JS_CONSOLE_ERRORS(SF «Pages with JavaScript Errors»):#1015страница, в консоли которой при отрисовке были зафиксированы ошибки. Данные читаются офлайн из сохранённых sidecar-файлов консоли нативного сканирования, без повторной отрисовки. Запись, которую нельзя прочитать, — это явный пропуск, а не чистая страница. Требуется
#1015 (задача на GitHub)rendering.artifacts.console_errors.ИзмененоРаботаетСканирования теперь сообщают четыре отсутствующих заголовка безопасности на HTML-страницу#1013
из сохранённого финального…
Сканирования теперь сообщают о четырёх отсутствующих заголовках безопасности для каждой HTML-страницы по сохранённому финальному ответу:
#1013 (задача на GitHub)MISSING_CSP,MISSING_X_CONTENT_TYPE_OPTIONS,MISSING_X_FRAME_OPTIONS(закрывается директивой CSPframe-ancestors) иMISSING_REFERRER_POLICY. Страницы, чьи сохранённые заголовки не удаётся разобрать, считаются неизмеренными, а не чистыми. Сканирование без сохранённого результата пропускает их с указанием причины.ДобавленоРаботаетДобавлен валидатор закрытых спецификаций действий на странице (
click,scroll,#1011
#1011 (задача на GitHub)wait_for_selector,wait_ms) со статическим бюджетом времени для сканирований с отрисовкой. Он пока не подключён к отрисовке, поэтому поведение сканирования не меняется (#1011).ИзмененоРаботает
log-analyzeчитает журналы доступа в формате gzip (ротированныеaccess.log.N.gzи#1009переименованные архивы)…
#1009 (задача на GitHub)log-analyzeчитает журналы доступа в формате gzip напрямую (ротированныеaccess.log.N.gzи переименованные архивы), определяя формат по содержимому, а не по расширению файла. Обрезанный или повреждённый архив выводится как ошибка без частичных подсчётов.ИзмененоРаботает
scan-url-queryполучает готовые пресеты представлений (--preset, например#1007
#1007 (задача на GitHub)status_4xx,title_missing,title_over_60,h1_missing,noindex_meta), которые объединяются логикой И с фильтрами пользователя. Параметр--export PATHвместе с--export-format csv|xlsxзаписывает все подходящие строки в новый файл. Экспорт отказывается работать сверх--export-max-rows(по умолчанию 100 000) и никогда не перезаписывает файл.ИзмененоРаботаетПравила допустимости rich result вынесены из исходного кода Python в#1001
#1001 (задача на GitHub)seohead/data/rich_results_rules.json— версионированный файл данных, поставляемый вместе с пакетом. Полеversionэтого файла проставляется какrules_versionв каждом вердикте rich result, поэтому изменение правила означает изменение данных, а не кода.ИзмененоРаботаетВердикты rich result (
check_schemaи проверки по сохранённым структурированным данным)#1001теперь несут
#1001 (задача на GitHub)rules_version, поэтому каждый результат называет набор офлайн-правил, который его выдал.ИзмененоРаботаетДобавлено описание шести служебных и генераторных скриптов, на которые в документации не#997
было ссылок…
В
#997 (задача на GitHub)docs/README.mdдобавлено описание шести служебных и генераторных скриптов, на которые в документации не было ссылок:scripts/generate_project_catalogue.py,generate_registry_inventory.py,render_readme_visuals.py,linux_lifecycle_smoke.py,capacity_watchdog.py,profile_million_audit.py. Указано, что каждый из них записывает и какие запускаются в CI (#997).ДобавленоРаботаетКонвейер семантического ядра добавлен как
seohead/semanticsсо своей SQLite-базой на#995каждый проект:
#995 (задача на GitHub)seohead semantics <stage> --project DIR(init, import, collect, clean, graph, exact, cluster, competitors, synonyms, report, excel, mine, sitematch, relevance, status, export), инструменты MCPseo_semantics_status,seo_semantics_run,seo_semantics_mineиseo_semantics_paid(платным стадиям нуженconfirm_paid=true), кластеризация Louvain за новым дополнениемsemantics, упакованный скиллsemantic-coreи синтетический пример проекта. Платные вызовы провайдера в стадиях семантики помечаются в общем журнале расходов (#995).ИзмененоРаботаетУдалён адаптер Telegram-бота с пошаговым режимом
seohead/integrations/bot; квитанции#995доставки мониторинга теперь хранятся в
#995 (задача на GitHub)seohead/projects/service_delivery.py(#995).ИзмененоРаботает
scan-url-queryвозвращаетclick_depth— кратчайший путь по внутренним ссылкам от#992стартовой страницы сканирования — как колонку, фильтр и ключ сортировки. Страницы, до которых не доходит ни одна сохранённая ссылка, получают
#992 (задача на GitHub)NULL(орфаны).crawl_depthне меняется и остаётся глубиной фронтира: для каждого URL, добавленного из sitemap, она равна 0. Если сканирование не сохраняло свои ссылки, запрос завершается сreason_code: click_depth_unavailable, а не выдаёт ложныйNULL. Значение пересчитывается при каждом запросе по таблицеlinks; сохранение его как индексированной колонки по завершении сканирования пока открыто, потому что требует решения о версии схемы (#992).ИзмененоРаботает
scan-url-queryи его инструмент MCP принимают необязательный аргументfacets(список#991групп или all)…
#991 (задача на GitHub)scan-url-queryи его инструмент MCP принимают необязательный аргументfacets(список идентификаторов групп илиall) и за один проход по тем же фильтрам возвращают счётчики по группам:status_2xx–5xx,title_missing,canonical_missing,directives_noindex/nofollow,with_outlinks. Группы, которым нужна проекция (внутренние/внешние, sitemap, дубли и длина title, canonical на себя или на другой URL), пока не включены.ИзмененоРаботаетПривязки источников проекта, первый срез (#990):
project-sources-link,#990
#990 (задача на GitHub)project-sources-unlinkиproject-sources-list(CLI, а такжеseo_project_sources_link|unlink|listчерез MCP) записывают, какие ID ресурсов провайдера использует проект, в файлsources.jsonрядом сproject.json. Работает только офлайн: без обнаружения, без вызовов провайдера и без учётных данных;project.jsonникогда не переписывается.ИзмененоРаботаетНативное сканирование: новая проверка IMG_BROKEN (#989, срез 1) сообщает о целях <img>,#989
которые ответили 4xx/5xx, и указывает страницу-источник как доказательство. Она читает сохранённый граф ресурсов и честно пропускает проверку, если ни одно изображение не было измерено.
#989 (задача на GitHub)ДобавленоРаботаетДобавлен чистый классификатор soft-404 по сохранённому телу страницы#988
(
#988 (задача на GitHub)classify_stored_soft404): пустой текст, фраза об ошибке на тонкой странице и совпадение simhash с шаблоном 404. Он пока не подключён к сканированию и не выдаёт находок; это первый срез задачи #988.ИзмененоРаботаетНативные сканирования проверяют цели canonical и hreflang, до которых не дошла ни одна#987
ссылка, по одному разу на цель после сканирования (не более 5 000). Если цель отвечает 4xx/5xx или редиректом, выводятся CANONICAL_TARGET_ERROR, CANONICAL_TO_REDIRECT или HREFLANG_BROKEN_TARGET, как это уже происходило для просканированных целей (#987).
#987 (задача на GitHub)ИзмененоРаботаетНаходки по цепочкам редиректов и петлям из нативного сканирования теперь содержат полный#985
путь переходов (
#985 (задача на GitHub)details.path), поэтому при исправлении можно назвать каждый переход, который нужно заменить. См. #985.ИзмененоРаботаетНаходки по цепочкам редиректов и петлям из нативного сканирования теперь также содержат#985
#985 (задача на GitHub)details.inbound_links(внутренние ссылки, которые всё ещё ведут на первый URL цепочки, с анкорами, не более 20) иinbound_links_count. Если инвентаря all_inlinks нет, поле равноnullи указана причина. См. #985.ИзмененоРаботаетПроекты могут записывать ссылку на семантическое ядро как факты, введённые оператором#984
(
#984 (задача на GitHub)semcore_project,semcore_cluster_count,semcore_landing_mapping). Само ядро хранится в собственной базе и не сливается с базой проекта; обнаружение никогда не записывает эти факты, а переданный факт не может заявлять происхождение «обнаружение». Описано вdocs/PROJECTS.mdв разделе «Linking a semantic core» (частично, #984).ИзмененоРаботаетDesktop: экран Link graph следует дизайну GraphFilters (холст и панель фильтров).#975
Ядро пока не возвращает весь граф ссылок, поэтому холст показывает честное состояние ожидания, а фильтры остаются неактивными, пока этого не появится (#975).
#975 (задача на GitHub)ИзмененоРаботаетOAuth для GSC:
provider-auth --action cancel(CLI) иseo_provider_auth#964
#964 (задача на GitHub)action=cancel(MCP) отменяют ожидающую запись потока согласия в браузере;statusпоказывает ожидающий поток, если он есть. Запись потока не хранит данных доступа и истекает через десять минут. Это первый срез #964: запуска и callback в браузере пока нет, поэтому публичная поверхность не создаёт потоков, а подключённый доступ по-прежнему не заявляется.ИзмененоРаботает
crawl-site --urls/--urls-file --projectтеперь регистрирует сканирование по списку URL#962как запуск наблюдателя (
#962 (задача на GitHub)mode=list), поэтому он появляется вproject-observeиproject-scansвместе с артефактом в каталогеscans/проекта. Сбойный сборщик записывается какfailed; прогресс и возобновление запусков по списку пока не поддерживаются (#962).ДобавленоРаботаетДобавлен структурированный план плейбуков:
skill-listиscenario-listвозвращают#955упорядоченные шаги каждого плейбука, а
#955 (задача на GitHub)skill-showиscenario-showдобавляют его заголовки и шаги, чтобы агент мог читать форму метода без разбора markdown (#955). Новая команда CLIscenario-listи инструмент MCPseo_scenario_list.ИзмененоРаботает
scan-content-searchпринимает--kind regex(MCPkind="regex"), чтобы искать по#954сохранённым документам регулярным выражением Python. Некорректные выражения отклоняются до начала сканирования. Документ, который превысил бюджет времени для регулярного выражения, отмечается как недоступный, а не как отсутствующий.
#954 (задача на GitHub)ИзмененоРаботаетВызовы DataForSEO с потерянным ответом (сетевая ошибка после отправки запроса)#949
записываются в журнал как…
Вызовы DataForSEO, ответ на которые потерян (сетевая ошибка после отправки запроса), записываются в журнал с
#949 (задача на GitHub)cost_unknownиcharge_status: unknown, поэтомуspend-reportпоказывает их как неопределённые, а не засчитывает как измеренный вызов с нулевой стоимостью (#949).ДобавленоРаботаетНовая команда
scan-structured-blocks(CLI) и инструмент MCP#948
#948 (задача на GitHub)seo_scan_structured_blocks: для одного сохранённого URL описывает каждый блок JSON-LD — строку источника, статус (valid/errors/warnings/parse_error), типы, плоский список свойств, ограниченный исходный JSON и ошибки графа Schema.org. Работает офлайн только по сохранённому полному телу страницы: без сетевых запросов и без изменений артефактов.ИзмененоРаботает
crawl-siteбез проекта, пишущий SQLite-артефакт сканирования, теперь делит потолок#942запросов на хост…
#942 (задача на GitHub)crawl-siteбез проекта, который записывает SQLite-артефакт сканирования, теперь делит потолок запросов на хост с другими параллельными сканированиями того же хоста через приватное расписание в каталоге состояния пользователя (~/.config/seohead/.origin-pacing.sqlite). Раньше сканирования без проекта шли без регулирования темпа между процессами.ИзмененоРаботаетПрофили crawl-site (#941):
crawl-profile listпечатает имена сохранённых профилей и…#941Профили crawl-site (#941):
#941 (задача на GitHub)crawl-profile listвыводит имена сохранённых профилей, аcrawl-profile delete NAMEудаляет один из них. Обе команды выводят JSON и отклоняют неизвестные имена, показывая список сохранённых профилей.ИзмененоРаботаетПрофили crawl-site (#941):
--save-profile NAME --config FILEсохраняет проверенную#941конфигурацию сканера как именованный профиль (отказ, если в ней есть заголовки с учётными данными);
#941 (задача на GitHub)--profile NAMEсканирует с ним, а--setпо-прежнему применяется поверх. Профили хранятся в~/.config/seohead/crawl-profilesили в каталоге, указанном вSEOHEAD_CRAWL_PROFILES. Просмотр и удаление профилей в этот срез не входят.ИзмененоРаботает
compare.v1теперь перечисляет страницы, просканированные только с одной стороны#938(
#938 (задача на GitHub)url_sets:only_in_before,only_in_after, счётчики). Если любое из сканирований частичное,url_sets.unprovenравен true, поэтому отсутствие не подаётся как доказательство.ИзмененоРаботаетПереходы в цепочках редиректов и canonical записывают статус, следующий Location#930
(редиректы) и время ответа…
Переходы в цепочках редиректов и canonical записывают статус каждого перехода, следующий Location (для редиректов) и время ответа, поэтому цепочку URL можно прочитать по сохранённым данным без повторного запроса (#930).
#930 (задача на GitHub)ИзмененоРаботаетПетли редиректов в цепочках по URL завершаются маркерным шагом (
{"url": ..., "loop": true}#930), который повторно не запрашивается, поэтому повторяющийся URL виден в сохранённых данных;
#930 (задача на GitHub)final_urlпо-прежнему указывает на последний запрошенный переход (#930).ДобавленоРаботаетШаги create и scan-ingest журнала remediation выводятся в CLI и MCP:
remediation-create#926/
#926 (задача на GitHub)seo_remediation_createсоздаёт один новый пустой журнал, привязанный к проекту (producer_buildдолжен быть полным 40-символьным Git SHA; существующие пути отклоняются), аremediation-ingest/seo_remediation_ingestпринимает один сохранённый аудит как baseline/history без повторного сканирования (повторный приём той же ревизии идемпотентен). Логика хранения не изменилась; это первый срез #926.ИзмененоРаботает
crawl_siteи запуски сканирования сообщаютeffective_max_requests_per_secondи#925
#925 (задача на GitHub)warnings: предупреждение выводится, когда эффективная частота выше 2 req/s (порог строго больше 2). CLI печатает то же предупреждение в stderr; JSON в stdout и значения по умолчанию не меняются. Регулятор темпа (pacer) не изменялся.ИзмененоРаботаетСтруктурированный журнал событий проекта (
events.jsonl): добавляемые события с#923источником, автором и ограниченным текстом, которые читаются от новых к старым постранично с фильтрами по источнику и тексту. Доступно как
#923 (задача на GitHub)project-event-append/project-event-pageв CLI и какseo_project_event_append/seo_project_event_pageчерез MCP (#923).ДобавленоРаботаетДобавлены команда
ai-columnи инструмент MCPseo_ai_column, первый срез AI-столбца…Добавлены команда
ai-columnи инструмент MCPseo_ai_column, первый срез пользовательского AI-столбца (см. #1012). По выбранным сохранённым страницам сканирования или переданным нормализованным элементам он готовит ограниченный план из title, заголовков и фрагмента текста с оценкой размера в символах (без применения цены) и с областью согласия, которую вызывающий агент обязан соблюсти до любой передачи данных. Переданные значения по каждому URL проверяются по хэшу исходника страницы: отсутствующие, устаревшие, пустые или слишком большие значения помечаются как таковые и никогда не подставляются. Необязательный CSV, безопасный для формул, экспортирует столбец. SEOHEAD не хранит ключ провайдера и не делает вызовов модели.ИзмененоРаботаетОбщие открыватели SQLite (только для чтения и для записи) вынесены в
seohead.core.sqlite.Читатели хранилищ, импортёр сканирований, архив GSC, хранилище источников, хранилище evidence-join и два класса проверок теперь открывают свои базы через один помощник: подключение, row factory и PRAGMA. Два класса проверок явно закрывают свои соединения. Поведение не изменилось; нормализация путей и порядок PRAGMA остаются на месте каждого вызова.
ИзмененоРаботаетИсправления корректности по итогам ревизии проверок, источников данных и импорта
доказательств.
Намеренные изменения поведения на этих путях: - Цепочки редиректов ровно с лимитом переходов (по умолчанию 20) теперь разрешаются, а не отмечаются как неразрешённые. Проверка петель выполняется раньше проверки лимита — и при разрешении цепочек, и при обходе путей переходов. - Проверки доверия и цитирования в EEAT сравнивают хосты назначения вместе с портом (
netloc), так же как логика хостов внутренних ссылок. У сайтов с явными портами результаты могут измениться. - Проверки ключевых слов в llms.txt сопоставляют ASCII-термины как целые слова с необязательным множественным числом, поэтомуrapid,ShowcaseиToolbarбольше не проходят. Кириллические основы по-прежнему совпадают как подстроки. - Захват навигации сопоставляет причинуreloadсrefresh_navigation. Несопоставленные запрошенные причины, напримерpageBlockInterstitial, записываются как наблюдения фреймов, которые валидатор принимает. - Определение технологий трактует отрицательную импликацию (["not", X]) как ничего не подразумевающую. - Импорт доказательств отклоняет повторяющиеся объявленные имена метрик, а обнаружение в Search Console использует переданные ему строки. - Повторные попытки Yandex Cloud ждут только между попытками. Повторные попытки в query-analytics Yandex Webmaster откатываются назад до следующей попытки. - Построение схемы передаёт свойtimeoutв HTTP-клиент (по умолчанию без изменений). - Хранилище квитанций доставки создаётся с режимом 0600 до того, как SQLite его откроет. - Запуски семантического графа сериализуются, потому что набор стоп-слов — состояние модуля. Семантический раннер сообщает об ошибках SQLite какok: false, а не выбрасывает исключение. - Парсер ошибок CrUX терпим к телам ответов, которые не являются объектами. - Удалена недостижимая проверкаsqlite3 is Noneв журнале.ИзмененоРаботаетDesktop: экран Backlinks в макете design-v2.
Он показывает честное состояние ожидания, пока ядро не сохранит профиль ссылок проекта (#999); строк-примеров нет, а фильтры групп отключены с той же причиной.
ИзмененоРаботаетDesktop, экран Crawler: баннер временных результатов с выбранным адресом и текстом
статуса…
Экран Desktop Crawler: добавлен баннер временных результатов с выбранным адресом и текстом статуса (показывается, только если сканирование без проекта вернуло результаты). Действия «очистить» и «сохранить как проект» перенесены в меню переполнения ниже 1000 px, поле адреса и полоса вкладок проверок остаются пригодными на узкой ширине, заголовок результатов прокручивается вместо сжатия колонок, а строка состояния оболочки получила такой же правый отступ 8 px в тёмной и светлой темах.
ИзмененоРаботаетDesktop: экран фатальных состояний по холстам ErrorsCore: отсутствие ядра, мало места на
диске и нет доступа на запись…
Desktop: экран фатальных состояний по холстам ErrorsCore — отсутствие ядра, мало места на диске и отсутствие доступа на запись показываются по реальным фактам; версия ядра и целостность сканирования показывают нейтральную плашку "unavailable in this core version", пока ядро не начнёт их передавать.
ИзмененоРаботаетDesktop: меню строки URL и меню заголовка колонки, группы строки меню Edit, Scan и
Window, а также контекстные меню находок и задач соответствуют доске Menus на холсте. Пункты, которые ядро пока не предоставляет, остаются видимыми, но неактивными, а причина указана во всплывающей подсказке.
ИзмененоРаботаетDesktop: экран «Export and reports» следует холсту ProjExport (выбор наборов данных…
Desktop: экран «Экспорт и отчёты» следует дизайн-холсту ProjExport (выбор наборов данных и формата, карточка папки, последние экспорты). Наборы данных и форматы, которые ядро пока не умеет экспортировать (compare, tasks, PDF), показаны как недоступные; кнопка запуска остаётся неактивной, пока экспорт не подключён (#1191).
ИзмененоРаботаетНейтрализация ведущих TAB и CR в идентификаторах маркетинговой инвентаризации и CSV-ревью
черновиков meta description…
Нейтрализация ведущих TAB и CR в идентификаторах маркетинговой инвентаризации и в CSV ревью черновиков meta description тем же апострофом, которым уже закрыты
=,+,-и@. Оба защитных правила теперь используют общую функциюseohead.core.tabular.neutralize_formula.ИзмененоРаботаетЗапросы к провайдерам с учётными данными (Arsenkin, Metrika, Yandex Cloud, IndexNow,
Topvisor, BI-назначения) больше не следуют HTTP-редиректам, поэтому заголовок Authorization никогда не уходит на другой хост. Редирект теперь возвращается как ошибка HTTP провайдера.
ДобавленоРаботаетФормат редиректов
csv(строкиsource,target,301, в кавычках при необходимости) в…Добавлен формат редиректов
csv(строкиsource,target,301, в кавычках при необходимости) вgenerate_ruleи в справку CLIredirects-generate. Форматwordpress-redirectionне включён, потому что его синтаксис импорта не проверен (#998).ИзмененоРаботаетЖурнал запусков (
runs.jsonl) теперь ротируется, когда превышает предельный размер (поумолчанию 5 MiB; переменная
SEOHEAD_RUN_LOG_MAX_BYTESзадаёт свой). Предыдущее поколение сохраняется какruns.jsonl.1, а чтение охватывает оба файла, поэтому поиск повторного использования результатов по-прежнему видит недавние вызовы.ИзмененоРаботаетВкладка Schema карточки URL в десктопе выстроена по структуре design-v2 (список блоков…
Вкладка Schema карточки URL в десктопном приложении выстроена по структуре design-v2: список блоков, дерево блоков, проверки. Ядро возвращает только количество блоков JSON-LD для каждого URL, поэтому колонки показывают честные состояния ожидания, привязанные к issue 948 в ядре. Известные количества остаются реальными, примеры блоков не показываются.
9 октября 2026 г.
4 добавлено4 измененоДобавленоРаботаетПодписи терминала на RU и EN по выбранной локали, блок прогресса текущего скана, явный#951
выбор скана…
Добавлены подписи терминала на RU и EN по выбранной локали, блок прогресса текущего скана, явный выбор скана и компактный вывод наблюдателя.
#951 (задача на GitHub)ИзмененоРаботаетСохранённые сканы открываются в облегчённом режиме для чтения (#931).#931
#931 (задача на GitHub)scan-status,scan-url-detail,scan-link-inspectи наблюдатель проекта (project-scans,project-observe) больше не проверяют весь артефакт при каждом открытии. Они проверяют идентичность, схему, версию и строку заголовка, берут счётчики из SQL (GROUP BYпоpages_status) и сообщают об этом в дополнительном полеvalidation("light"или"full"). Полная проверка выполняется по запросу (full_validation: trueвscan-statusили--input '{"input_path": "...", "full_validation": true}'в CLI) либо если те же байты (путь, размер, mtime, состояние WAL, хэш заголовка) уже были полностью проверены в этом процессе. Скан, не прошедший облегчённые проверки, отклоняется с той же ошибкой, что и раньше. Каждый путь записи или фиксации доказательств по-прежнему проверяет всё полностью.scan-url-detailвыполняет поиск цели редиректа (индекса поresponses.effective_url_idнет) в рамках бюджета 0,5 с и сообщаетresponses.redirect_target_lookupкакskipped, вместо того чтобы сканировать большую таблицу.ДобавленоРаботаетОбщее аудируемое состояние MCP с отзывом при запуске и на лету; безопасное присутствие#929
клиентов в CLI…
Добавлено общее аудируемое состояние MCP с отзывом при запуске и на лету для вызовов инструментов. Безопасное присутствие клиентов показывается через CLI.
#929 (задача на GitHub)ДобавленоРаботаетРегистрация клиентов с явного разрешения: предпросмотр, атомарная запись, проверенные…#929
Добавлена регистрация клиентов с явного разрешения: предпросмотр, атомарная запись, проверенные резервные копии и восстановление без конфликтов.
#929 (задача на GitHub)ДобавленоРаботаетДобавлен
scan-url-query(MCPseo_scan_url_query): только чтение, с серверной#927фильтрацией…
Добавлен
#927 (задача на GitHub)scan-url-query(MCPseo_scan_url_query): только чтение всей таблицы страниц одного сохранённого скана, с серверной фильтрацией, сортировкой и постраничной выдачей. Ответ содержитtotal,filtered_total(nullиfiltered_total_state: capped, если подсчёт превысил свой временной бюджет), проекцию столбцов, метки покрытия скана, форматseohead.scan-url-query.v1и машиночитаемыйreason_codeпри каждой ошибке. За один вызов — не более 200 строк. Сортировка поurl,status_code,page_ordinalилиurl_idиспользует индексы. Для любого другого столбца нужен фильтр, который оставляет не более 100 000 строк (иначеsort_not_indexed). Скан открывается с облегчённой проверкой идентичности и поколения схемы, а не полной валидацией, и никогда не изменяется.ИзмененоРаботает
scan-link-inspect --view links(MCPseo_scan_link_inspect) постранично выводит ссылки…#924
#924 (задача на GitHub)scan-link-inspect --view links(MCPseo_scan_link_inspect) постранично выводит исходящие или входящие гиперссылки URL, найденного по адресу, а не по ID документа. Для каждой ссылки показываются анкорный текст,relс флагами nofollow/sponsored/ugc, внутренняя или внешняя, сохранённая позиция, атрибутtargetи HTTP-статус другого конца (null, если та страница не сканировалась). Фильтры: тип ссылки, флаг follow, класс статуса и подстрока.offset/limitдо 200.total/filtered_totalточные либо помечены как capped. Скан открывается только для чтения без полной валидации, ошибки содержат машиночитаемыйreason_code(url_not_found,scan_not_available,url_not_scanned,links_not_retained). Существующие представления и поля не изменены.ИзмененоРаботаетСтруктура пакетов переработана без совместимых заглушек:
seohead.serversтеперь…Структура пакетов переработана без совместимых заглушек.
seohead.serversпереименован вseohead.mcp,seohead.tools— вseohead.checks,seohead.botиseohead.remote_apiперенесены вseohead.integrations. CLI теперь живёт в пакетеseohead.cli(сseohead.cli.terminal_progress). Общие корневые модули (models,graph,filesystem,runlog,verification,canonical_policy,input_contracts,job_contracts,provider_matrix) перенесены вseohead.core, а сведения о происхождении сборки — вseohead._build.provenance.examples/иconfig.example.jsonперенесены вdocs/examples/,PROVENANCE.mdиTRADEMARKS.md— вdocs/legal/. Командыseoheadиsf-analyzerне изменились, но импорты Python по старым путям модулей нужно обновить.ИзмененоРаботаетREADME переписан вокруг установки, трёх сценариев быстрого старта (нативное сканирование
до отчёта…
README переписан вокруг установки: три сценария быстрого старта (нативное сканирование до отчёта, офлайн-экспорты Screaming Frog, проект плюс агент), карта возможностей по областям, обзор CLI, настройка MCP для Claude Code и Claude Desktop, сопутствующее десктопное приложение и граница между измеренным и неизмеренным. Скриншоты реального терминала лежат в
docs/assets/, сняты на локальной QA-фикстуре и синтетической фикстуре экспорта. Добавленdocs/CLI.md: он группирует каждую зарегистрированную команду по задаче с пометками о сети, записи и платности. Тест на расхождение с командами падает, если команда отсутствует. Добавленdocs/WORKFLOWS.md, где описаны команды запуска воркфлоу, inbox и записей монитора, которые раньше упоминались только в справочнике.
8 октября 2026 г.
1 добавлено10 изменено1 исправленоИсправленоРаботаетУчёт байтов сохранённых HTML/DOM ведётся внутри транзакции и инкрементально, а не…#914
Учёт байтов сохранённых HTML/DOM ведётся внутри транзакции и инкрементально, без пересканирования всех сохранённых тел для каждого уникального ответа. Writer-ы, открытые повторно, один раз пересчитывают счётчик. Дедупликация, откат, savepoint-ы и лимиты хранения тел продолжают работать.
#914 (задача на GitHub)ИзмененоРаботаетВ BI-отчётности непроверенные состояния сбора провайдеров и флаги качества остаются#833
неизвестными в…
В BI-отчётности непроверенные состояния сбора данных провайдеров и флаги качества остаются неизвестными в метриках, покрытии и манифестах. Подтверждённые семплирование, пороговая фильтрация или усечение делают данные частичными. Когортам «поиск против сессий» нужны явное качество сбора, неотрицательные счётные измерения и квалифицированные области источников. Для каждой оси сохраняются идентичность источника, атрибуция, область поиска и календарная политика. Синтетический отчётный пакет остаётся офлайн, нативная приёмка для Sheets и Looker выполняется отдельно.
#833 (задача на GitHub)ИзмененоРаботаетНативные SQLite-сканирования сайта принимают
max_urls=0, чтобы собирать, пока очередь#818не исчерпана…
Нативные SQLite-сканирования сайта принимают
#818 (задача на GitHub)max_urls=0(собирать, пока очередь не исчерпана) иmax_depth=-1(отключить ограничение глубины). Бюджеты по времени и HTTP настраиваются отдельно, защита хранилища и прерывание с возобновлением продолжают работать. Устаревшие материализованные маршруты отказываются работать с неограниченным набором URL.ИзмененоРаботаетСканирования только по Sitemap тоже сохраняют отключённый лимит URL, а не отказываются на#818
первом…
Сканирования только по Sitemap тоже сохраняют отключённый лимит URL и не отказываются от первого объявленного элемента, когда настроенный лимит равен нулю.
#818 (задача на GitHub)ИзмененоРаботаетЯвно заданные конечные частоты запросов выше стандартных 2 запросов/с теперь доходят до#818
общей…
Явно заданные конечные частоты запросов выше стандартных 2 запросов в секунду теперь попадают не только в ограничитель отдельного скана, но и в общую полосу регулирования темпа по origin проекта. Параллельные сканы по-прежнему резервируют одно общее расписание для хоста, а не умножают его частоту.
#818 (задача на GitHub)ИзмененоРаботаетПрерывание нативного анализа теперь возвращает явный результат «прервано, можно#754
продолжить» и сохраняет собранные страницы вместо утечки трейсбека KeyboardInterrupt.
#754 (задача на GitHub)- ИзмененоРаботаетПересобрать упакованный каталог проектов после обновления сценария провайдера Bing.#754 (задача на GitHub)
ИзмененоРаботаетОтклонять некорректные строки ответа Bing Webmaster вместо полного пустого результата…#753
Некорректные строки ответа Bing Webmaster отклоняются, а не выдаются за полный пустой результат. Сырые данные ответа, исходные строки и точные возвращённые количества сохраняются в доказательствах провайдера. Ответы с количеством ссылок сохраняют задокументированную постраничную структуру, а многостраничные совокупности помечаются как частичные, если собрана только одна запрошенная страница.
#753 (задача на GitHub)ИзмененоРаботаетУчёт существующего общего резервного service account Google в готовности провайдера GA4…#753
В готовности провайдера GA4 и поиске учётных данных учитывается существующий общий резервный service account Google. Права аккаунта и доступ к цели остаются непроверенными, некорректные учётные данные явно сообщаются, а поддержка OAuth bearer сохраняется без требования обоих источников.
#753 (задача на GitHub)ИзмененоРаботаетПривязка ссылок на возможности headless к изоляции нативных запусков и публичной…#743
Ссылки на возможности headless привязаны к изоляции нативных запусков и публичной границе маршрутизации внешнего сканирования. Внутренняя реализация отделена от доступности в CLI и MCP, поведение сканирования и заявлений о производительности не меняются.
#743 (задача на GitHub)ДобавленоРаботаетОграниченная постраничная выдача финальных запусков в
project-observe(CLI и MCP) ссохранением…
Добавлена ограниченная постраничная выдача запусков в финальных состояниях в
project-observe(CLI и MCP), при этом каждая сохранённая запись о выполняющемся запуске остаётся видимой. Страницы сохраняют точные ID запусков и обратный порядок поступления. Счётчики и метаданные хранения описывают текущее хранилище на 100 записей, а не всю историю. Чтение не меняет сохранённые состояния выполнения. JSON-входы CLI сохраняют пагинацию и область проекта, если явный именованный флаг не переопределяет их.ИзмененоРаботаетCtrl+C обрабатывается на всём этапе передачи после сбора, включая открытие…
Ctrl+C обрабатывается на всём нативном этапе передачи после сбора: открытие сохранённого скана, необязательные последующие фазы, анализ и финализация. Незавершённые захваты сохраняют свои данные и возобновляемую контрольную точку и возвращают явный JSON-результат «interrupted». Прерывание после финального коммита сохраняет готовый артефакт и сообщает его фактическую доступность аудита. Явное возобновление доводит незавершённую работу после сбора до конца даже при исчерпанном фронтире, сохраняя существующие флаги пропуска доказательств и сохранённые входы sitemap.
7 октября 2026 г.
4 добавлено4 изменено1 исправленоДобавленоРаботаетОдноразовая Linux-фикстура приёмки для выполнения воркеров по SSH с ключом…#754
Добавлена одноразовая Linux-фикстура приёмки для настоящего выполнения воркеров по SSH с ключом, аутентифицированных загрузок API/TLS и ошибки ENOSPC нативного воркера на ограниченном tmpfs только для заданий. Очередь и доказательства сохраняются. До запуска свежего задания восстановления JS требуется явный результат, отличный от успеха, без повторного выполнения. Уточнено, что локальные замеры жизненного цикла отличаются от доказательств по SSH и изоляции ОС.
#754 (задача на GitHub)ИзмененоРаботаетСохраняются частичные доказательства JavaScript в результатах удалённых заданий, включая#754
исправление старых завершённых заданий только для чтения, без изменения сохранённых артефактов и бюджетов рендеринга. Восстановление очереди из бэкапа проверено через аутентифицированный статус, загрузки и постоянную идемпотентность. Фикстура восстановления из двух страниц остаётся на полном рендеринге в пределах своих конечных бюджетов.
#754 (задача на GitHub)ИзмененоРаботаетКод выхода 130 без трейсбека, когда SIGINT прерывает финальный вывод JSON после…
Код выхода 130 без трейсбека, когда SIGINT прерывает финальный вывод JSON уже после завершения обработчика. Сохранённые артефакты не меняются, обрезанный поток вывода никогда не считается успешным.
ДобавленоРаботаетФиксируется стратегия области контента, которой получены сохранённые хэши и количество
токенов…
Фиксируется стратегия области контента, использованная для получения сохранённых хэшей и количества токенов, а не стратегия области по умолчанию парсера. Явные селекторы и исключения теперь имеют совпадающее происхождение извлечения, даже если парсер страницы использовал свою область по умолчанию.
ИсправленоРаботаетНеопубликованные staging-файлы нативного SQLite не попадают в историю сканов и кандидатов
на очистку…
Неопубликованные staging-файлы нативного SQLite не попадают в историю сканов и в кандидаты на очистку. Некорректные опубликованные файлы по-прежнему отмечаются, а обычные скрытые сканы с именем, заданным пользователем, разрешены.
ДобавленоРаботаетДобавлен нативный сбор SQLite только по Sitemap: явный sitemap задаёт полную запрошенную
совокупность URL без запасного старта со стартовой страницы, без расширения по гиперссылкам и без расширения по целям редиректов. Пустые, неполные и превышающие бюджет совокупности sitemap останавливаются явно. Возобновление повторно использует сохранённую совокупность без повторной загрузки XML.
ИзмененоРаботаетОтдельные записи запусков проекта сохраняются для одновременных нативных захватов, а
общий…
Отдельные записи запусков проекта сохраняются для одновременных нативных захватов, а для одного и того же публичного хоста используется общий проектный шлюз отправки на 2 запроса в секунду. Наблюдатели видят для каждого запуска тип источника, origin, отпечаток конфигурации и совокупную границу частоты.
ДобавленоРаботаетОфлайн-поиск по точной строке в сохранённых HEAD, HTML, тексте тела и разметке, выбранной
CSS-селекторами…
Добавлен офлайн-поиск по точной строке в сохранённых HEAD, HTML, тексте тела и разметке, выбранной CSS-селекторами. Поиск показывает покрытие статичной и отрендеренной версии, неизвестные отсутствующие тела, необязательные сниппеты с замаскированными данными и постраничную выдачу новых локальных пакетов результатов с проверкой целостности.
ИзмененоРаботаетСохранённые настройки сканирования Screaming Frog сохраняются при экспорте: load-crawl
больше не…
При экспорте сохранённого сканирования Screaming Frog сохраняются его собственные настройки: load-crawl больше не подставляет текущую конфигурацию сканера. Запуски сканера и по списку URL по-прежнему получают свои явные профили для каждого запуска.
6 октября 2026 г.
9 добавлено14 изменено9 исправленоИзмененоРаботаетТесты собственного внешнего захвата одинаково разрешают виртуальные loopback-хосты в#896
разных ОС…
Тесты собственного внешнего захвата одинаково разрешают свои виртуальные loopback-хосты в разных операционных системах, без изменения сетевой политики в продакшене.
#896 (задача на GitHub)ИсправленоРаботаетВвод в терминале работает выше предела дескрипторов select, а Delete и неподдерживаемые#896
управляющие последовательности не стирают…
Ввод в терминале работает и при количестве дескрипторов выше предела select, а клавиша Delete и неподдерживаемые управляющие последовательности не стирают несохранённые заметки.
#896 (задача на GitHub)ИзмененоРаботаетСохраняются версионированные события навигации в браузере с ограниченными пропусками,#826
состоянием захвата, политикой рендерера и происхождением URL. Различаются наблюдаемые HTTP-редиректы, навигация Chromium через скрипты, историю и фрагменты, а также события с неизвестной причиной. Утверждения о действиях человека, например о кликах, не делаются.
#826 (задача на GitHub)ДобавленоРаботаетТе же доказательства доступны через render-check и ограниченные офлайн-отчёты#826
scan-navigation. Частичные наблюдения сохраняются, если рендеринг не удался.
#826 (задача на GitHub)ИзмененоРаботаетСовместимость при откате сохраняется: доказательства навигации хранятся внутри#826
расширяемых настроек рендерера. Более ранняя предрелизная кодировка проверяется без ослабления проверок происхождения. Наблюдаемые события не считаются политикой рендерера.
#826 (задача на GitHub)ИсправленоРаботаетБольшие вложенные сводки, включая гистограммы глубины, в полных сопутствующих PDF…#818
Большие вложенные сводные совокупности, включая гистограммы глубины, сохраняются в полных сопутствующих PDF-файлах и не учитываются в ограниченном бюджете метаданных для отображения. Именованные назначения, оглавление и внутренние ссылки сохраняются при переписывании ссылок сопутствующего PDF клонированием полного PDF-документа.
#818 (задача на GitHub)ДобавленоРаботаетЯвный
pdf_policy="overview-v1"для запросов PDF по сохранённому audit.v2.#818Первая страница различает полное количество исходных, показанных и опущенных элементов. Детерминированные префиксы отображения сохраняют полные состояния покрытия и причины и ведут к полному потоковому JSON аудита и сопутствующим CSV: findings, pages и scope. Манифест с хэшами и количествами фиксирует происхождение и ресурсные лимиты. Существующие пути назначения отклоняются, экспорт сначала готовится во временных файлах, а маркер завершения PDF публикуется только после проверки всех обязательных сопутствующих файлов. Поведение PDF по умолчанию не меняется: обзор никогда не выбирается неявно и не описывается как исчерпывающий PDF. Точные границы и семантика сбоев — в
#818 (задача на GitHub)docs/PDF_OVERVIEW.md.ДобавленоРаботаетОперация провайдера GA4
page_viewsтолько для чтения: просмотры по дате, хосту и пути…#782Добавлена операция провайдера GA4
#782 (задача на GitHub)page_viewsтолько для чтения: количество просмотров по дате, имени хоста и посещённому пути, независимо от сессий по посадочным страницам. Используются существующие учётные данные GA4, транспорт и постраничный читатель отчётов с ограниченными повторами, исходами по квотам и правам доступа, явными метаданными часового пояса, семплирования и порогов, а также привязкой URL к заявленному origin. Сохранённые ограниченные доказательства провайдера нормализуются через существующее объединение и конвейер BI. Отсутствующий трафик остаётся недоступным, а не становится нулём.ИсправленоРаботаетОбновления наблюдателя остаются ограниченными: покрытие по сайтам переиспользуется, живая#777
активность сборщика проецируется…
Обновления наблюдателя остаются ограниченными: покрытие по сайтам переиспользуется, активность живых сборщиков выводится отдельно, а находки audit.v2 выдаются постранично без материализации посторонних коллекций графа.
#777 (задача на GitHub)ИзмененоРаботаетКаждый активный сборщик сохраняется в ограниченной истории, публикуются измеренные#777
счётчики с отметками времени, а неизмеренные счётчики отличаются от нуля. Проверенный прогресс Screaming Frog передаётся потоком с ограничением обоих диагностических каналов.
#777 (задача на GitHub)ДобавленоРаботаетСтраницы только для чтения: чек-лист, детали задачи и сохранённые сканы, а также явная…#777
Добавлены страницы только для чтения: чек-лист, детали задачи и сохранённый скан, а также явная область применимых методов и проекция последних входящих.
#777 (задача на GitHub)ИсправленоРаботаетЗапуски Sitemap с явной привязкой остаются отдельными: счётчики в процессе неизвестны, а…#777
Запуски Sitemap с явной привязкой остаются отдельными: счётчики в процессе остаются неизвестными, а итоговые измерения считают разобранные документы Sitemap отдельно от заявленных URL, ошибок и усечений.
#777 (задача на GitHub)ИзмененоРаботаетКвитанции артефактов чек-листа отслеживаются по защищённым метаданным файла без…#777
Квитанции артефактов чек-листа отслеживаются по защищённым метаданным идентичности файла, без повторного хэширования сохранённых байтов при обновлении. Явное чтение покрытия по-прежнему проверяет байты. Изменённые доказательства или доказательства старого формата, не прошедшие проверку, остаются видимыми как устаревшие или непроверенные.
#777 (задача на GitHub)ИсправленоРаботаетИсторические квитанции приоритетов остаются привязанными к исходной области элементов,#777
когда новые задачи добавляются после подготовки. Каждый полный кандидат покрытия проверяется до атомарной публикации. Детальные чтения данных конкурентов в рамках области сохраняют пассивную проверку только по метаданным.
#777 (задача на GitHub)ДобавленоРаботаетЯвное сравнение сохранённых аудитов через диск с полными результатами в NDJSON…#762
Добавлено явное сравнение сохранённых аудитов через диск с полными результатами в NDJSON, детерминированным порядком, идентичностями источников, контрольными суммами по файлам и сохранением находок до и после. Для больших сравнений audit.v2 нужен новый каталог вывода. Дублирующиеся идентичности и коллизии соответствия URL завершаются ошибкой, а не теряют строки.
#762 (задача на GitHub)ИсправленоРаботаетЦелевая проверка audit.v2 остаётся ограниченной при дубликатах строк, сохраняет#762
проверенную идентичность…
Целевая проверка audit.v2 остаётся ограниченной при наличии дублирующихся строк, в выбранных документах сохраняется проверенная идентичность скана. Конфликтующие идентичности и сканы «после» с ошибками не принимаются как доказательство исправления.
#762 (задача на GitHub)ДобавленоРаботаетПотоковое сжатие gzip по выбору для полных файлов NDJSON compare.v2…#762
Добавлено потоковое сжатие gzip по выбору для полных файлов NDJSON compare.v2: детерминированные сжатые байты и точные хэши сжатых файлов с количеством декодированных строк и байтов. Добавлен ограниченный читатель, который проверяет обычные и gzip-экспорты и отклоняет повреждённые потоки и несовпадающие количества из манифеста. По умолчанию вывод остаётся обычным.
#762 (задача на GitHub)ИсправленоРаботаетСовместимость сравнения сохранённых корпусов остаётся неизвестной, если отсутствует любой#762
флаг полноты…
Совместимость сравнения сохранённых корпусов остаётся неизвестной, если отсутствует любой из флагов полноты, а известные частичные корпуса явно предупреждаются. Идентификаторы и причины пропущенных и отключённых проверок сохраняются вместе с дельтами находок, чтобы отсутствующие измерения нельзя было выдать за подтверждённое исправление.
#762 (задача на GitHub)ИзмененоРаботаетНаблюдатель проекта в терминале читает задачи, методы, структурированные данные, сканы…#752
Наблюдатель проекта в терминале позволяет просматривать читаемые детали задач, методов, структурированных данных, сканов, запусков, входящих и сохранённых доказательств: постранично и с честным указанием покрытия. Чтения из хранилища и явная отправка заметок вынесены из цикла ввода.
#752 (задача на GitHub)ИзмененоРаботаетЧерновики заметок и целей сохраняются отдельно в рамках сессии, поддерживается#752
редактирование курсором, сохраняется…
Черновики заметок и целей сохраняются отдельно в рамках сессии, поддерживается редактирование курсором, крупная вставка сохраняется без усечения, квитанции о сохранении показываются в любой раскладке, а несохранённые черновики выводятся после обычного выхода из терминала для восстановления.
#752 (задача на GitHub)ДобавленоРаботаетЯвный просмотр покрытия и артефактов собственного сайта и конкурентов, выбранный сайт#752
сохраняется…
Добавлен явный просмотр покрытия и артефактов собственного сайта и конкурентов. Выбранный сайт сохраняется на страницах скана и находок, в подсказках показываются недавние предложения конкурентов на основе заметок, а прогресс измеренного сбора виден в компактных терминалах. Устаревшие выборки больше не анимируются как живой прогресс.
#752 (задача на GitHub)ДобавленоРаботаетВерсионированный инвентарь возможностей headless, сформированный из реальных настроек#743
сканера…
Добавлен версионированный инвентарь возможностей headless, сформированный из реальных настроек сканера, со ссылками на реализацию, CLI/MCP, тесты и явно обозначенные пробелы в приёмке.
#743 (задача на GitHub)ДобавленоРаботаетБенчмарк HTML/JavaScript на собственном origin по выбору с зафиксированными фазами,#743
деревом процессов…
Добавлен бенчмарк HTML/JavaScript на собственном origin (по выбору) с зафиксированными фазами, бюджетами памяти дерева процессов, диска и восстановления. Измеряемые DOM создают настоящие браузеры. Сам по себе профиль не подтверждает производительность обработки JavaScript на больших сайтах.
#743 (задача на GitHub)ИсправленоРаботаетИсправлен неподдерживаемый аргумент streaming в нативном JavaScript-мосте, а уже#743
наблюдённые…
Исправлен неподдерживаемый аргумент streaming в нативном JavaScript-мосте. Уже наблюдённые счётчики рендеринга сохраняются при штатной отмене и возобновлении.
#743 (задача на GitHub)ИзмененоРаботаетlog-scan читает сохранённые пути нативных сканов и сопутствующие audit.v2 без…#711
log-scan читает сохранённые пути нативных сканов и сопутствующие файлы audit.v2 без материализации устаревшего JSON. Находки о согласованности стримятся, принадлежность нативных страниц и дедупликация находок остаются на диске, точное количество аномалий сохраняется, а ограничиваются только примеры. Явно сообщается об отсутствии нативной трассы решений об исключениях.
#711 (задача на GitHub)ИзмененоРаботаетНаходка lastmod в sitemap для всего сайта распознаётся на корневом origin измеренного#711
сайта, если не…
Находка lastmod в sitemap для всего сайта распознаётся на корневом origin измеренного сайта, если главная страница не сканировалась. Исключение требует совпадения сводных данных sitemap и не освобождает от находок по страницам, посторонних хостов или неподдерживаемых целевых путей.
#711 (задача на GitHub)ИзмененоРаботаетСравнение сохранённых сканов audit.v2 по точному ключу и порядковому индексу без…
Сравнение сохранённых сканов audit.v2 идёт по точному ключу и порядковому индексу, без дублирования данных страниц и находок во временном хранилище SQLite. Полные строки, детерминированные экспорты в обычном и gzip-виде, идентичности источников и устаревшие входы по-прежнему поддерживаются. Читатели аудита закрепляют проверенный снимок через индексированные чтения строк.
ИзмененоРаботаетОткат собственных членов сравнения при поздней ошибке публикации и отказ от конкурентно
появившихся мест назначения; манифест остаётся финальным маркером фиксации пакета.
ИзмененоРаботаетСделать публичную точку входа описанием настраиваемой SEO-инженерии с агентами и ссылками…
Публичная точка входа описывает настраиваемую SEO-инженерию с агентами и связывает полный набор возможностей с их методами, входными данными и границами доказательств. Исправлены устаревшие указания про нативный сканер, SF, покрытие проектов и устранение проблем. Рабочая книга разработчика, которую пишет агент, теперь описана отдельно от фактических отчётов, включая утверждённые критерии приёмки и ссылки на источники.
ИсправленоРаботаетВосстановить паритет человекочитаемых отчётов между потоковыми входами audit.v2 и
эквивалентным JSON аудита.
Markdown теперь использует общий инкрементальный рендерер, включая объяснения недоступных проверок, записи об исключениях и итоговые примечания о покрытии. XLSX использует общую раскладку метаданных и пишет находки и страницы через ограниченные листы только для записи, сохраняя все листы, колонки, фильтры, диаграммы и счётчики источников. Сохранённые подавленные находки воспроизводятся без материализации их коллекции, а отсутствующие URL запуска используют тот же запасной вариант — первую страницу.
ИзмененоРаботаетМаркировать происхождение PDF-аудита независимо от общей схемы аудита: нативный сканер…
Маркировать происхождение данных PDF-аудита независимо от общей схемы аудита: нативный сканер, экспорты Screaming Frog или явно указанный сборщик SF, а также неизвестный сборщик. Нативный аудит, использующий схему SF Analyzer, больше не получает заголовок Screaming Frog.
ИзмененоРаботаетПотоково записывать строки области подавленных находок в CSV вместо накопления их
отрисованных объяснений…
Потоково записывать строки области подавленных находок в CSV вместо накопления отрисованных объяснений в памяти. Полные экспорты исключений сохраняют порядок и исходные факты, а выделение памяти остаётся ограниченным даже для больших коллекций сохранённых исключений.
5 октября 2026 г.
1 измененоИзмененоРаботаетСверять каждую строку пробелов покрытия по её фактической ячейке Mode, проверять ссылки#830
на проверки и инструменты…
Сверять каждую строку пробелов покрытия по её фактической ячейке Mode, проверять ссылки на покрытые проверки и инструменты по публичным реестрам и формировать приоритеты из нерешённых строк.
#830 (задача на GitHub)
4 октября 2026 г.
56 добавлено75 изменено5 исправленоДобавленоРаботаетДобавить офлайн-проекцию прогресса GSC по брендовым и небрендовым запросам с явными#880
алиасами с учётом Unicode, совместимым взвешенным CTR и подписанными полосами средней позиции.
#880 (задача на GitHub)ДобавленоРаботаетДобавлена необязательная группировка задач
check_assignmentдля объявленных#878сопоставлений URL шаблонов и компонентов или проверенных сегментов сканирования. Сгруппированные рабочие элементы сохраняют счётчики вхождений и URL, ограниченные доказательства, происхождение группировки, границы проверки и состояния declared, candidate, confirmed и unassigned.
#878 (задача на GitHub)ДобавленоРаботаетДобавить опциональные карты сравнения релизов
url-correspondence.v1с объявленными#877origin и парами URL…
Добавлены опциональные карты сравнения релизов
#877 (задача на GitHub)url-correspondence.v1с объявленными origin и парами URL, отказом при коллизиях, происхождением данных страниц и выводомrelease_review.v1.ДобавленоРаботаетДобавить офлайн-проекцию когорт публикаций с подтверждёнными данными и происхождением дат…#876
Добавить офлайн-проекцию когорт публикаций с подтверждёнными данными, происхождением дат, инвентаризацией авторов, подписанными наблюдениями провайдеров и необязательными окнами возраста.
#876 (задача на GitHub)ДобавленоРаботаетДобавить офлайн-инвентаризацию CTA и встроенных форм с сохранением вхождений для#875
переданного HTML: с допускаемыми пустыми целями, ограниченным выводом JSON/CSV и явным указанием неполного покрытия тела страницы.
#875 (задача на GitHub)ИзмененоРаботаетСохранять классификацию таймаутов удалённых запросов при редактировании ошибок транспорта#866
и безопасно воспроизводить манифесты прокси…
Сохраняется классификация таймаутов удалённых запросов при редактировании ошибок транспорта; прямые манифесты прокси безопасно воспроизводятся для целевой проверки.
#866 (задача на GitHub)ИзмененоРаботаетЧитать данные атрибуции из сохранённого SQL-графа ссылок, сохранять явный null при#866
экспорте…
Читать данные атрибуции из сохранённого SQL-графа ссылок, сохранять явное null-значение атрибуции при экспорте и сохранять проверки внешних ссылок в буфере при возобновлении.
#866 (задача на GitHub)ИзмененоРаботаетПересобрать интегрированные каталоги и контракты отчётов; установить валидатор PDF с#866
дополнением all…
Пересобраны интегрированные каталоги и контракты отчётов; валидатор PDF устанавливается с дополнением all, а тесты с фейковым браузером не зависят от выбора локального Chrome.
#866 (задача на GitHub)ДобавленоРаботаетДобавить необязательный офлайн-план загрузки в BigQuery с версионированными по схеме#837
таблицами, требованиями к оплате…
Добавить необязательный офлайн-план загрузки в BigQuery: версионированные по схеме таблицы, требования к оплате и явные предварительные условия авторизации без доступа к облаку.
#837 (задача на GitHub)ДобавленоРаботаетДобавить транспорт BigQuery REST через allowlist с детерминированными заданиями загрузки#837
в staging, сверкой числа строк и задокументированной атомарной публикацией по таблицам, а не фиктивной транзакцией между таблицами.
#837 (задача на GitHub)ИзмененоРаботаетТребовать отдельного одобрения
cost_authorizedот хост-приложения для BigQuery перед#837любым токеном, проверкой датасета или записью в staging.
#837 (задача на GitHub)ДобавленоРаботаетДобавить локальный валидируемый построитель ссылки копирования Looker Studio для#836
синтетического пакета из пяти страниц…
Добавить локальный валидируемый построитель ссылки копирования Looker Studio для синтетического пакета отчётов из пяти страниц. Он требует ID исходного отчёта и точные алиасы источников Sheets или BigQuery, не публикует отчёт и не придумывает шаблон.
#836 (задача на GitHub)ДобавленоРаботаетДобавить зафиксированную синтетическую фикстуру рабочих листов#836
(
examples/reporting-pack/worksheets/)…Добавлена зафиксированная синтетическая фикстура рабочих листов (
#836 (задача на GitHub)examples/reporting-pack/worksheets/): один CSV на каждый набор данных BI плюс манифест, детерминированно сгенерированные байт в байт изexamples/audit.jsonи двух синтетических входов GSC/GA4. Она демонстрирует состояния: измеренный ноль, подавленные и отсутствующие данные, только внешние, без ключа, пропущенные проверки, недоступный набор данных и неполный квадрант. Воспроизводимость проверяется черезscripts/generate_reporting_pack_worksheets.py --check.ДобавленоРаботаетДобавить
examples/reporting-pack/SETUP.md: механическое руководство владельца по#836импорту…
Добавлен
#836 (задача на GitHub)examples/reporting-pack/SETUP.md: механическое руководство для владельца по импорту шести листов в Google Sheets, подключению зарезервированных алиасов источников данных, построению пяти страниц блюпринта с объявленными элементами управления и вычисляемыми полями, включению разрешения на копирование и проверке свежей копии. Нативный шаблон Looker Studio остаётся внешним шагом, который разрешает владелец. ID отчёта, ссылка и запись в Google не включены.ИзмененоРаботаетСохранять имена разделов, счётчики и контрольные суммы сгенерированного BI-пакета, чтобы#836
фикстура рабочих листов проходила существующую предварительную проверку Sheets и потребителей отфильтрованного экспорта. Задокументированы отдельные поля алиасов Linking API; требуется проверка свежей копии по сгенерированной ссылке без ручного исправления источников.
#836 (задача на GitHub)ИзмененоРаботаетОтклонять дублирующиеся алиасы Linking API после нормализации пробелов и возвращать#836
точные алиасы, использованные в параметрах URL. Определены общие ID полей запуска, сгруппированные элементы управления датами провайдеров и диаграммы покрытия, которые исключают пересекающиеся совокупности. Создание нативного шаблона и проверка свежей копии остаются внешними требованиями приёмки.
#836 (задача на GitHub)ДобавленоРаботаетДобавить явные подтверждённые строки когорт URL в локальные BI-пакеты, включая…#835
Добавить явные строки когорт URL с подтверждёнными данными в локальные BI-пакеты, включая квадранты Search Console и GA4, безопасные для измеренного нуля, только для полностью совместимых наблюдений «один к одному».
#835 (задача на GitHub)ИзмененоРаботаетРассчитывать наблюдаемые доли входящих ссылок по уникальным страницам-источникам в#835
области с завершённым извлечением HTML, сохраняя повторные вхождения отдельно и помечая частичные совокупности.
#835 (задача на GitHub)ДобавленоРаботаетДобавить типизированные детерминированные офлайн-BI-пакеты для сохранённых сканирований,#834
аудитов и данных провайдеров…
Добавить типизированные детерминированные офлайн-BI-пакеты для сохранённых сканирований и аудитов и переданных данных провайдеров с границами разделов, состояниями null, сохранением строк и безопасными для формул ячейками CSV.
#834 (задача на GitHub)ИзмененоРаботаетСохранять находки из ограниченных companion-файлов audit.v2, объединять до 1 000 000#834
сохранённых URL сканирования через долговечный SQLite-артефакт доказательств и потоково передавать этот артефакт в BI без материализации списков страниц и совпавших URL. Это не даёт копируемого шаблона Looker Studio.
#834 (задача на GitHub)ИзмененоРаботаетПроецировать группы находок, кандидатов квадрантов провайдеров и допустимые источники#834
входящих ссылок через ограниченный одноразовый SQLite-индекс. Динамические измерения провайдеров остаются корректными в выбранных экспортах и офлайн-планах Sheets и BigQuery. Количество разделов и потребление диска ограничены.
#834 (задача на GitHub)ИзмененоРаботаетСохранять целевые URL и сообщения находок нативного аудита как типизированные BI-колонки,#834
а не только внутри сохранённого исходного JSON, чтобы точные выборки URL учитывали затронутые находки.
#834 (задача на GitHub)ДобавленоРаботаетДобавить
scan-fragment-links(seo_scan_fragment_links) и проверку аудита#827BROKEN_BOOKMARK…Добавлены
#827 (задача на GitHub)scan-fragment-links(seo_scan_fragment_links) и проверка аудитаBROKEN_BOOKMARK: каждый<a href>с фрагментом в сохранённом полном HTML или DOM сопоставляется с id элементов и целями<a name>целевого документа по алгоритму WHATWG прокрутки к фрагменту. Сначала сериализованный фрагмент проверяется по id и именам, затем декодированное по процентам и UTF-8 значение проверяется по обоим;+остаётся обычным плюсом, а#и#topведут к началу документа. Статическое, отрисованное и устаревшее представления оцениваются независимо, учитываются правила редиректов и<base href>, а другая строка запроса означает другой документ. Отсутствующие, обрезанные, неподдерживаемые, неудачные или исчерпавшие бюджет тела фиксируются как именованные пропуски, а не как битые находки. Экспорты Screaming Frog и устаревшие импорты явно указывают, что проверка недоступна, а не что она прошла чисто. Результаты ограничены и детерминированно постранично выводятся (total,returned,offset/limit,next_offset, состояние покрытия). Они одинаковы в CLI, MCP и в сводке аудита сохранённого сканирования. Ничего не загружается: оценка только для чтения и офлайн.ИзмененоРаботаетПроверять нативные обратные ссылки hreflang по полным сохранённым объявлениям целевых#825
URL, различая известное отсутствие обратной ссылки и цель, которая не просканирована или недоступна по телу. Сообщать о наблюдаемых альтернативах с noindex, сохранять исходные метки и нормализованные идентификаторы URL с контекстом дубликатов и конфликтов, помечать частичные связи совокупностей как не измеренные. Существующие поверхности аудита, CLI, MCP и отчётов передают те же находки без дополнительной загрузки.
#825 (задача на GitHub)ДобавленоРаботаетДобавить
CANONICAL_TARGET_ERRORдля загруженных канонических целей, которые отвечают#8244xx или 5xx…
Добавлена
#824 (задача на GitHub)CANONICAL_TARGET_ERRORдля отчётов о загруженных канонических целях, которые отвечают 4xx или 5xx. Она содержит доказательства источника, цели, ответа и индексируемости. Неизвестные цели или цели с неполным статусом остаются недоступными. Известные варианты 2xx снимают вердикт об ошибке, а цели 3xx остаются подCANONICAL_TO_REDIRECT.ДобавленоРаботаетДобавить
CANONICAL_HOMEPAGE_GROUPдля групп минимум из трёх загруженных индексируемых#824страниц…
Добавлена
#824 (задача на GitHub)CANONICAL_HOMEPAGE_GROUPдля групп минимум из трёх загруженных индексируемых страниц в двух и более разделах пути с разными title и H1, которые каноникализируются на загруженную главную. Страницы self и home, страницы с query, распознаваемая пагинация, настроенные шаблоны пагинации и фильтров, неполные доказательства главной и частичные нативные сканирования не дают находок уровня сайта.ДобавленоРаботаетДобавить объективные доказательства авторства, дат и страниц доверия в ограниченные#823
аудиты (issue #823)…
Добавлены объективные доказательства авторства, дат и страниц доверия в ограниченные аудиты (issue #823): восемь проверок уровня notice в
#823 (задача на GitHub)seohead/sf/core/eeat.py. Они сообщают то, что может увидеть сканирование, и никогда не выставляют оценку E-E-A-T.NO_AUTHOR_BYLINEиNO_CONTENT_DATESсрабатывают только на страницах, похожих на контент: тип статьи в JSON-LD,og:type=article, элемент<article>или типичный путь контента. Они называют носители, которые читают (meta_author,rel_author,itemprop=author, классbyline,<time datetime>, JSON-LDauthor/datePublished/dateModified, путь URL с датой), и у каждого заявлена достоверность.MISSING_ABOUT_PAGE,MISSING_CONTACT_PAGE,MISSING_PRIVACY_POLICYиMISSING_TERMS_PAGEсообщают одно из состояний:found_indexable(молчит),found_non_indexable,found_error,discovered_not_crawledилиnot_discovered. Поэтому страница, которая существует, но не отдаётся, не выглядит так же, как страница, на которую никто не ссылается.FEW_CITATIONSсообщает только то, что могут доказать позиции ссылок: исходящую ссылку внутри текста статьи или заявленный нулевой счётчик.YMYL_REVIEW_CANDIDATEотмечает детерминированные совпадения пути и заголовка по целым словам для проверки человеком, а не классификацию. Не измеренное всегда отличается от отсутствующего: страница, тело которой не разбиралось, сохраняетtrust_signalsкак NULL и учитывается в причине пропуска.summary.trust_evidenceфиксирует оценённую область, состояние страниц по типам и оговорку о частичном сканировании для вердиктовnot_discovered.ИзмененоРаботаетКлассифицировать p75 полевых LCP, INP и CLS текущего окна CrUX по версионированным#822
официальным порогам…
Классифицировать p75 полевых значений LCP, INP и CLS текущего окна CrUX по версионированным официальным порогам, сохраняя область URL или origin, форм-фактора и периода сбора. Отсутствующие, неполные и неудачные полевые данные остаются недоступными или частичными.
#822 (задача на GitHub)ДобавленоРаботаетДобавить явную ограниченную выборку URL с необязательным приватным кэшем и принимать#822
сохранённые данные CrUX…
Добавлена явная ограниченная выборка URL с необязательным приватным кэшем. Сохранённые данные CrUX принимаются в аудитах сайтов и отчётах без автоматических запросов к провайдеру. Ограничивается объём ответов и кэша, а несогласованные сохранённые счётчики выборки и повторяющиеся записи URL отклоняются вместо отчёта о полном покрытии полевых данных.
#822 (задача на GitHub)ИзмененоРаботаетЗадокументировать текущую границу одноразового Docker CLI отдельно от необязательного…#820
Задокументирована текущая граница одноразового Docker CLI отдельно от необязательного явно создаваемого удалённого API и рабочего сервиса.
#820 (задача на GitHub)ДобавленоРаботаетДобавить рецепт запуска по SSH с постоянным рабочим пространством и пояснить, что#820
состояние выхода и артефактов CLI…
Добавлен рецепт запуска по SSH с постоянным рабочим пространством. Пояснено, что состояние выхода CLI и артефактов не является проверкой работоспособности HTTP-сервиса.
#820 (задача на GitHub)ИзмененоРаботаетДопустить явные нативные конфигурации сканирования SQLite до 1 000 000 URL с отдельным…#818
Допускаются явные нативные конфигурации сканирования SQLite до 1 000 000 URL с отдельным бюджетом 2 000 000 HTTP-запросов и существующим синтетическим профилем только для хранения. CLI, MCP, удалённая очередь и воркеры сохраняют одинаковые объявленные бюджеты. Материализованные legacy и list API сохраняют явное ограничение безопасности в 50 000 URL. Проверки robots, повторы, переходы редиректов и канонических ссылок теперь делят один бюджет запросов. Нативные аудиты и офлайн-переанализ используют ограниченный путь audit.v2 без прежнего отказа по мосту на 10 000 страниц или 20 000 форм. Счётчики транзакционного писателя не пересматривают растущий фронтир на каждом батче. Ручной драйвер приёмки фиксирует идентификаторы загруженных источников, прерывание и возобновление, а также последующих потребителей. Допуск сам по себе не является доказательством завершённой приёмки на миллион URL.
#818 (задача на GitHub)ИзмененоРаботаетЗапускать каждый этап ручной нативной приёмки под сторожевым таймером ресурсов#818
подпроцесса…
Каждый этап ручной нативной приёмки запускается под сторожевым таймером ресурсов подпроцесса. Прерванные артефакты сохраняются, проверяется каждая строка CSV и XLSX и покрытие задач. Защищённый HTTP на собственном loopback проверяется отдельно с неизменным стандартным темпом.
#818 (задача на GitHub)ИзмененоРаботаетРазрешить явно авторизованную длительность удалённого сканирования до 14 дней, сохраняя#818
часовой…
Разрешена явно авторизованная длительность удалённого сканирования до 14 дней. Часовое значение по умолчанию сохраняется, как и независимые бюджеты проекта, запросов, диска, lease и рендеринга. Это позволяет миллионной цели уложиться в неизменную вежливую частоту запросов. Значения выше потолка длительности и некорректные типы отклоняются до начала сбора данных.
#818 (задача на GitHub)ИзмененоРаботаетОфлайн-переанализ использует свежий дедлайн для каждой операции SQLite execute и fetch.#818
Прерывание запроса и отмена сохраняются, а время разбора Python и производных записей не списывается с исходного дедлайна проверки открытия скана.
#818 (задача на GitHub)ИзмененоРаботаетLegacy
crawl-site --out-dirтеперь хранит доказательства страниц, ссылок и форм в#817append-only JSONL sidecar-файлах…
Legacy
#817 (задача на GitHub)crawl-site --out-dirтеперь хранит доказательства по страницам, ссылкам и формам в append-only JSONL sidecar-файлах во время сбора и возобновления, вместо удержания дублирующих списков в памяти. Контрольные точки проверяют счётчики sidecar-файлов. Более старые контрольные точки v4 с встроенными формами мигрируют без потери находок по формам. Существующий мост аудита называет свои границы материализации страниц, форм и ссылок и сохраняет собранные доказательства, когда аудит недоступен. Предыдущий отчёт сохраняется под устаревшим именем файла, а не выдаётся за текущий запуск. Нативная эскалация JavaScript читает записи страниц через перечитываемое представление SQLite, а не пересобирает все объекты страниц. Потоковая обработка больших аудитов полностью остаётся в #816/#817.ИзмененоРаботаетХранить слишком большие нативные аудиты в упорядоченных companion-файлах audit.v2 вместо#817
отбрасывания доступности аудита…
Слишком большие нативные аудиты сохраняются в упорядоченных companion-файлах audit.v2 вместо отбрасывания доступности аудита.
#817 (задача на GitHub)- ИзмененоРаботаетПотоково нормализовать нативный аудит в его контекст без промежуточного списка записей.#817 (задача на GitHub)
ИсправленоРаботаетХранить карты страниц нативного аудита и производные метрики по страницам во временном#817
контекстном SQLite-хранилище…
Карты страниц нативного аудита и производные метрики по страницам хранятся во временном контекстном SQLite-хранилище.
#817 (задача на GitHub)ИсправленоРаботаетХранить нативные находки на диске, пока упорядоченная агрегация не присвоит им#817
идентификаторы отчёта.
#817 (задача на GitHub)ИсправленоРаботаетХранить нативные группы дубликатов и контента в упорядоченном SQLite-хранилище во время#817
анализа.
#817 (задача на GitHub)ИзмененоРаботаетОграничить повторные поиски страниц, пакетно вычислять обратные ссылки для находок и#817
определять глубину нативного обнаружения…
Ограничиваются повторные поиски страниц, обратные ссылки для находок вычисляются пакетами, а глубина нативного обнаружения определяется без пересборки всех маршрутов и загрузки всех узлов в Python. Длинные маршруты сохраняют точную глубину и явные усечённые конечные точки.
#817 (задача на GitHub)ИзмененоРаботаетПотоково передавать сохранённый нативный ввод страниц и поиски входящих ссылок до#817
построения контекста.
Непустые связи корпуса и hreflang вычисляются через индексы на диске. Полные коллекции доказательств сохраняются в audit.v2, а ограниченные выборки связанных находок помечаются точным числом вхождений.
#817 (задача на GitHub)ИзмененоРаботаетОграничить кэш страниц оценкой декодированных байтов Python, а также числом записей;#817
некэшируемые крупные страницы…
Кэш страниц ограничивается оценкой декодированных байтов Python и числом записей. Некэшированные крупные страницы остаются читаемыми, а мутации сбрасывают вес старого кэша. Ранги размеров HTML хранятся как стабильные скалярные пары URL и размера вместо удержания всех полных моделей страниц. Сериализованный JSON страниц не сохраняется в колбэках мутаций.
#817 (задача на GitHub)ИзмененоРаботаетСохранять только скалярные факты URL, статуса, индексируемости, канонического URL и#817
редиректа при проверке пар с завершающим слешем…
При проверке пар с завершающим слешем сохраняются только скалярные факты: URL, статус, индексируемость, канонический URL и редирект. Соединения SQLite долговечного адаптера и удалённых задач закрываются явно.
#817 (задача на GitHub)ИзмененоРаботаетПотоково считать покрытие недоступных тел и кодировок, сохранять скалярное состояние#817
выбора страниц доверия…
Покрытие недоступных тел и кодировок charset считается потоково. Вместо кандидатских совокупностей страниц сохраняется скалярное состояние выбора страниц доверия. Совпадения DOM в сохранённом HTML обрабатываются в два прохода по фиксированному файловому индексу. Сохраняются порядок представительных нормализованных вариантов, существующие примеры URL, полное покрытие сопоставленных источников и каждая находка.
#817 (задача на GitHub)ИзмененоРаботаетПроверять legacy-JSONL контрольных точек сканирования построчно перед добавлением,#817
отказываясь от отсутствующих…
Legacy-JSONL контрольных точек сканирования проверяется построчно перед добавлением. Отсутствующие, повреждённые или незавершённые доказательства отклоняются без замены. Более старые контрольные точки со встроенными формами сравниваются с их sidecar-файлом без выделения второго списка форм.
#817 (задача на GitHub)ДобавленоРаботаетДобавить бенчмарк JavaScript с проверкой происхождения и продолжением между завершёнными#817
парами…
Добавлено продолжение бенчмарка JavaScript между завершёнными парами с проверкой происхождения. Более ранние квитанции и бюджеты диска сохраняются. Прерванные кейсы остаются явными блокерами. Кейс бенчмарка считается пройденным только при успешных запросе или переанализе и полных доказательствах в CSV страниц.
#817 (задача на GitHub)ИзмененоРаботаетСохранять явные списки URL в нативном SQLite-писателе с сохранением точного порядка входа…#817
Явные списки URL сохраняются нативным SQLite-писателем с точным порядком входа, несколькими хостами и семантикой без обнаружения. Входной файл обмена читается потоково. Бюджеты запросов и времени сохраняются при возобновлении сбора, ограниченные доказательства ответов и переходов сохраняются, а проверки графа и форм явно остаются недоступными. Большие списки каталогов используют тот же буфер с отдельно ограниченным JSON-мостом аудита.
#817 (задача на GitHub)ДобавленоРаботаетДобавить версионный companion audit.v2 в SQLite для полных упорядоченных коллекций аудита#816
сверх…
Добавлен версионный companion audit.v2 в SQLite для полных упорядоченных коллекций аудита сверх встроенного ограничения размера JSON, со связыванием происхождения скана и сквозной проверкой целостности.
#816 (задача на GitHub)ИзмененоРаботаетПотоково выводить отчёты audit.v2 в JSON, CSV, XLSX, Markdown и DOCX, сравнивать#816
совокупности находок высокого…
Отчёты audit.v2 в JSON, CSV, XLSX, Markdown и DOCX выводятся потоково, сравниваются совокупности находок высокого уровня. Операции snapshot и prune остаются парными с companion-файлом при сохранении схемы scan.v1.
#816 (задача на GitHub)ИзмененоРаботаетСохранять большие упорядоченные членства групп один раз в хранилище audit.v2 revision 3 и#816
реестре ledger revision 5…
Большие упорядоченные членства групп сохраняются один раз в хранилище audit.v2 (revision 3) и реестре ledger (revision 5). Обратно совместимое чтение аудитов, атомарная миграция реестра, явная постраничная выборка членов через CLI и MCP, а также полные BI-companion-файлы членства, привязанные к источнику.
#816 (задача на GitHub)ИзмененоРаботаетСохранять дайджест исходного audit.v2 при офлайн-переанализе; сохранять неполную область#816
групп реестра…
При офлайн-переанализе сохраняется дайджест исходного audit.v2. Неполная область групп реестра сохраняется, а ресурсы ingest закрываются при неудачной проверке.
#816 (задача на GitHub)ИзмененоРаботаетПовторно использовать точную сводку возможностей корпуса, пока нативное сканирование#815
только с метаданными не имеет…
Точная сводка возможностей корпуса переиспользуется, пока нативное сканирование только с метаданными не имеет ответов, документов, тел или данных ресурсов. Это избавляет от повторного чтения всего корпуса при каждой фиксации разреженной страницы, не меняя хранилище сканирования.
#815 (задача на GitHub)ДобавленоРаботаетОфлайн-профилировщик ёмкости нативного сканирования (включается явно) с раздельными#815
лимитами…
Добавлен офлайн-профилировщик ёмкости нативного сканирования, который включается явно. Он задаёт отдельные лимиты на ссылки, сохранённый HTML и отрендеренный DOM, явные бюджеты ресурсов и проверку потери процесса с возобновлением. Существующий потолок приёма в 50 000 URL и незавершённая финализация отражаются как заблокированные свидетельства, а не как измеренная ёмкость.
#815 (задача на GitHub)ИзмененоРаботаетОтмена закреплённого браузерного запроса получила код
render_cancelled.#811При отмене или разрыве соединения закрываются изолированный удалённый контекст и браузер, локальный фолбэк не используется.
#811 (задача на GitHub)ИзмененоРаботаетДоверенная удалённая конфигурация проекта может передавать ссылки на учётные данные из#810
окружения, привязанные к хосту. Происхождение сохраняется в виде, очищенном от секретов. Если ссылка недоступна, сбор не начинается.
#810 (задача на GitHub)ИзмененоРаботаетТранспорт удалённого Playwright с проверкой версии, управляемый сервисом, для задач в#809
очереди…
Для задачи проекта в очереди может использоваться удалённый транспорт Playwright, управляемый сервисом, с проверкой версии. Его endpoint не попадает в отправки, а запросы браузера остаются закреплёнными и подчиняются политике.
#809 (задача на GitHub)ДобавленоРаботаетНаблюдаемые пути, обратные входящие ссылки и контекст вхождений сохранённого скана в#807
одном запросе…
Наблюдаемые пути, обратные входящие ссылки и контекст вхождений сохранённого скана доступны через один ограниченный запрос только для чтения в общем CLI и MCP. Запрос привязан к явному идентификатору скана и возвращает ошибки в структурированном виде.
#807 (задача на GitHub)ДобавленоРаботаетОграниченное размещение ссылок на уровне вхождений и контекст ближайшего заголовка из…#806
Ограниченное, только для чтения размещение ссылок на уровне отдельных вхождений и контекст ближайшего заголовка из сохранённого статического HTML и отрендеренного DOM. Дубли ID ссылок сохраняются, а неполные или недоступные данные помечаются явно.
#806 (задача на GitHub)ДобавленоРаботаетНовая команда
semantic-inputs(seo_semantic_inputsв MCP) строит воспроизводимый#801манифест нормализованных входов для семантического сходства. Для каждого документа фиксируются хэш сохранённого тела, хэш точного декодированного входа, хэш нормализованного вывода, стратегия области контента и языковые признаки: собственный
#801 (задача на GitHub)<html lang>страницы и доли буквенных скриптов. Сам нормализованный текст не сохраняется.--scanчитает сохранённые полные тела офлайн по записанной конфигурации области контента, без повторного запроса. Отсутствующее или частичное тело остаётся явным пропуском, а не чистым пустым результатом (#801).ИзмененоРаботаетПроверка PDF технического аудита: число страниц, размер, извлекаемый текст и сохранение#800
записей модели…
Перед публикацией отчёта проверяются число страниц PDF технического аудита, размер в байтах, извлекаемый текст и сохранение всех записей исходной модели.
#800 (задача на GitHub)ДобавленоРаботаетОфлайн-вывод PDF через двуязычный Chromium в общие пути report-build в CLI и MCP…#799
В общие пути report-build в CLI и MCP добавлен офлайн-вывод PDF через Chromium с двуязычной версией. Временный файл проверяется и очищается до атомарной замены.
#799 (задача на GitHub)ДобавленоРаботаетСамодостаточные английская и русская вёрстки PDF технического аудита с нейтральными#798
токенами бренда…
Добавлены самодостаточные английская и русская вёрстки PDF технического аудита: нейтральные токены бренда, диаграммы серьёзности и покрытия, явные состояния неполного прогона и постраничный перенос длинного контента.
#798 (задача на GitHub)- ИсправленоРаботаетВёрстка PDF отделена от построения модели аудита и интеграции CLI и MCP.#798 (задача на GitHub)
ДобавленоРаботаетВерсионированная офлайн-модель контента PDF технического аудита с сохранением исходных…#797
Добавлена версионированная офлайн-модель контента PDF технического аудита. Она сохраняет исходные записи, точные исходные и спроецированные счётчики, область охвата и состояния покрытия для обоих поддерживаемых контрактов аудита.
#797 (задача на GitHub)ИзмененоРаботаетСохранение версий зарегистрированных сценариев workflow, контекста сайта и конкурентов,#796
доказательств по шагам…
Сохраняются версии зарегистрированных сценариев workflow, контекст сайта и конкурентов, доказательства по каждому шагу и контрольные точки проверки. Прерванные запуски может возобновить более поздняя локальная сессия, но только если их текущие зависимости всё ещё действительны.
#796 (задача на GitHub)ИзмененоРаботаетЗапуск workflow требует рабочего списка контроллера; квитанции разбора заметок#796
специалистов…
Запуск workflow требует рабочего списка контроллера. Квитанции разбора заметок специалистов сохраняются явно для исходов: задача, цель, конкурент, заблокировано или отклонено.
#796 (задача на GitHub)ИзмененоРаботаетУспешные контрольные точки workflow сверяют байты артефактов с квитанциями SHA-256…#796
Успешные контрольные точки workflow проверяют байты сохранённых артефактов, привязанных к проекту, по квитанциям SHA-256. Если доказательство отсутствует или изменилось, прежнее завершение считается устаревшим, но история не переписывается. Бюджеты проверки никогда молча не подтверждают доказательство и не отбрасывают его квитанцию.
#796 (задача на GitHub)ИзмененоРаботаетЯвные ограниченные профили политики хэшей доказательств; старые политики нормализуются.#796
Пассивная проверка наблюдения workflow смотрит сохранённые метаданные верификации и не пересчитывает хэши артефактов. Изменённые или непроверенные квитанции остаются явно помеченными.
#796 (задача на GitHub)ДобавленоРаботаетОграниченная постраничная команда CLI
project progressи инструмент MCP#795seo_project_progress…Добавлены ограниченная постраничная команда CLI
#795 (задача на GitHub)project progressи инструмент MCPseo_project_progress: счётчики состояний чек-листа и следующие действия. Представление использует результаты покрытия в заданной области. Процент выполнения аудита задач показывается только с явной пометкой и только если по каждому сайту в выборке согласован план и есть измеренный непустой знаменатель задач. Покрытие популяции URL остаётся отдельным показателем.ИзмененоРаботаетЧек-листы проекта теперь фиксируют согласованную область аудита и честное покрытие…#794
Чек-листы проекта теперь фиксируют согласованную область аудита и показывают честные коэффициенты покрытия (#794).
#794 (задача на GitHub)project-checklist-initиseo_project_checklist_initпринимают необязательныйplan: рецензента, популяцию URLpopulation, объявленную какcomplete_set, именованнуюsampleилиunknown, с еёsource,sizeили перечисленнымиurls, необязательные популяции поtemplatesи необязательное соглашение поtasks(all_agreedили выборкуselectionиз существующих ID пунктов чек-листа). План привязывается к идентичности сайта проекта и помечается номером ревизии записи. Запись плана переводит чек-лист наseohead.coverage.v3и добавляет запись в сохраняемую историю планов. Повторная запись того же соглашения ничего не меняет. Изменённое соглашение помечает прежние доказательства устаревшими, а не пересчитывает их с новым знаменателем. Однопланные документы v3 мигрируют при чтении. Чтение, сверка и применение приоритетов никогда не повышают версию и не создают популяцию. Документы v1 и v2 продолжают загружаться без изменений. Пункты вне выборки отображаются какnot_agreedи не входят ни в один знаменатель.ИзмененоРаботаетЗавершение чек-листа теперь следует измеренной области: автоматический пункт с частичным#794
сканом не засчитывается…
Завершение чек-листа теперь следует измеренной области. Автоматический пункт, привязанный к сайту и опирающийся на ограниченное (частичное сканирование) измерение, остаётся незавершённым и не считается выполненным. Пункт, привязанный к явным образцовым URL, завершается, когда артефакт покрывает ровно эту область. Верхний флаг
#794 (задача на GitHub)completeтеперь означает, что аудит в заданной области завершён: все применимые согласованные задачи выполнены, нет ожидающих исключений, а согласованная популяция URL полностью покрыта проверенными измерениями. Поэтому неизвестная или неизмеренная область никогда не даёт статус завершённого аудита.ИзмененоРаботаетСтатус чек-листа теперь возвращает
coverage: пять отдельных коэффициентов —#794audit_tasks,checks…Статус чек-листа возвращает
#794 (задача на GitHub)coverage: пять отдельных коэффициентов —audit_tasks,checks(сmeasured_urls),manual_review,deliverable_reviewиurl_population. У каждого свойbasis,numerator,denominatorиstate, поэтому счётчик URL никогда не смешивается со счётчиком проверок или задач. Знаменатель, который нельзя обосновать, остаётсяnullсstate: "unknown"и причиной, а не превращается в 0/0 или 100%. Измерения, которые нельзя проверить по согласованной популяции, сохраняют ось URL в состоянииpartialи учитывают только проверенные подходящие URL. Принадлежность URL проверяется по согласованному перечислению, поэтому популяция, заданная толькоsize, не засчитывает измеренных URL, и числитель никогда не превышает знаменатель. Популяции по шаблонам проверяются как согласованные подмножества популяции сайта при записи или чтении плана: перечисленные URL шаблона должны входить в перечисленный набор сайта, а объявленное членство в шаблоне не может превышать согласованный размер сайта. Некорректный план отклоняется, а не обрезается и не считается сверх знаменателя. Сохранённые доказательства проверок теперь содержат перечисление измеренных URL, поэтому числитель по URL является проверяемым набором, а не количеством строк. Агрегация по нескольким сайтам суммирует оси по каждому сайту и переходит вunknown, если сайт не может обосновать свой знаменатель.ИзмененоРаботаетЗапись
not_applicableтеперь проверенное исключение: нужны причина, рецензент…#794Запись
#794 (задача на GitHub)not_applicableтеперь проверенное исключение. Для неё нужны причина, рецензент и проверяемое основание: привязанный к проекту дайджестartifactили явная ссылкаevidence. Проверенные исключения сохраняют стабильный ID и историю, выходят из знаменателей задач только по зафиксированному решению и отдельно перечисляются вexclusions. Отключённый пункт, устаревшая запись исключения или старая записьnot_applicable, созданная до правила об основании доказательства, остаются в знаменателе какpending_exclusion, пока их снова не проверят. Поэтому отключение, удаление из каталога или переклассификация никогда молча не уменьшают согласованные счётчики. Свежее проверенное исключение для пункта, удалённого из каталога, закрывается штатно и не застревает в ожидании навсегда.ДобавленоРаботаетАдресуемый промпт
workflow/full-audit-v1и сценарийfull-auditчерез маршруты#793каталога CLI и MCP…
Добавлены адресуемый промпт
#793 (задача на GitHub)workflow/full-audit-v1и сценарийfull-auditчерез существующие маршруты каталога навыков и сценариев в CLI и MCP. Workflow использует уже поставляемые пути сбора и методики, а проверка и отчётность опираются на реальные доказательства. Подготовка проекта отделена от завершения полного аудита.ИзмененоРаботаетПривязка решений по исправлению к неизменяемым артефактам проверки и точным хэшам#792
доказательств до и после…
Решения по исправлению привязываются к неизменяемым артефактам проверки и точным хэшам доказательств «до» и «после», включая потоковые базовые линии audit.v2.
#792 (задача на GitHub)ИзмененоРаботаетРезультаты исправлений с состояниями покрытия «представлено» и «полный охват»,#791
знаменателями по задачам…
Результаты исправлений выводятся с состояниями покрытия «представлено» и «полный охват», знаменателями по каждой задаче и ограниченными постраничными выборками кейсов для больших реестров.
#791 (задача на GitHub)ДобавленоРаботаетОграниченные повторные проверки исправлений по ключу реестра с защищённым верификатором…#790
Добавлены ограниченные повторные проверки исправлений по ключу реестра. Они используют защищённый верификатор, потоково читают выборки audit.v2 и отказываются работать при смещении области.
#790 (задача на GitHub)ИзмененоРаботаетПроверка исправлений привязана к сохранённой идентичности аудита и исходной политике,#790
влияющей на результаты. Повторно использованный UUID скана сам по себе больше не открывает старый кейс.
#790 (задача на GitHub)ДобавленоРаботаетДобавлен реестр исправлений
ledger.v1(seohead.storage.ledger, идентификатор#788приложения
#788 (задача на GitHub)SEOL): отдельный SQLite-артефакт, привязанный к проекту. Он записывает находки, идентичность каждого вхождения, принадлежность затронутых URL и журнал наблюдений только на добавление из проверенных аудитовscan.v1иscan.v2, не меняя исходные сканы. Источник привязывается по UUID скана, ревизии доказательств, хэшу аудита и идентичности производителя и конфигурации. Точные повторы не меняют состояние, конфликтующие байты при той же ревизии отклоняются атомарно. Покрытиеcappedиaggregate_only, а также данныеunavailableсохраняются как данные и не считаются решёнными молча. Есть транзакционная миграция 0→1, полная проверка схемы и целостности при открытии иdocs/LEDGER.md(#788).ДобавленоРаботаетОдноразовый loopback-профиль TLS-реверс-прокси для проверки изоляции артефактов…#787
Добавлен одноразовый loopback-профиль TLS-реверс-прокси. Он проверяет изоляцию аутентифицированных артефактов, резервное копирование и восстановление, истечение срока и атомарный откат обновления, не разворачивая сервис.
#787 (задача на GitHub)ИзмененоРаботаетДокументированы разовые SSH CLI-задания, записи артефактов и инцидентов, синтетическое#787
восстановление и отдельная граница для будущего сервиса: проверка здоровья, прокси, TLS и файервол.
#787 (задача на GitHub)ДобавленоРаботаетПрофиль оператора self-hosted удалённого сервиса: приватные bind, аутентифицированная#787
проверка…
Добавлен профиль оператора self-hosted удалённого сервиса: приватные bind-адреса, аутентифицированные доказательства здоровья, ссылки на секретные файлы, записи инцидентов, восстановление SQLite с согласованностью данных, откат релиза и явное истечение срока терминальных артефактов.
#787 (задача на GitHub)ДобавленоРаботаетПолитика удалённых целей, привязанная к проекту, для будущих заданий в очереди.#786
При привязке воркером политика проверяет цели и настройки, повторно проверяет DNS при отправке, закрепляет HTTP- и браузерные запросы к ресурсам и соблюдает бюджеты запросов по каждому источнику и общий. Удалённые прокси и альтернативные браузерные движки по умолчанию блокируются, пока их выход в сеть не доказан безопасным.
#786 (задача на GitHub)ДобавленоРаботаетПроектно-изолированная очередь SQLite и воркер нативного сканирования с арендой для#785
необязательного API…
Добавлены проектно-изолированная очередь SQLite и воркер нативного сканирования с арендой для необязательного аутентифицированного удалённого API. Задания сохраняют нативные сканы и отчёты JSON/Markdown, поддерживают идемпотентную отправку, отмену, восстановление после сбоя при перезапуске, скоупные загрузки артефактов и явное хранение. Слушатель по умолчанию не включается.
#785 (задача на GitHub)ИзмененоРаботаетНеобязательный аутентифицированный версионированный контракт удалённого API сканирования…#784
Определён необязательный аутентифицированный версионированный контракт удалённого API сканирования: ограниченные настройки нативного сканирования, права в рамках проекта, идемпотентная отправка, схема OpenAPI и доказательства, совместимые со статусом скана. Нужны отдельные долговечные воркеры и политика целей и выхода в сеть. Локальные установки CLI и MCP не меняются (#784).
#784 (задача на GitHub)ДобавленоРаботаетЗакреплённый runbook для SSH на Ubuntu и одноразовый smoke-тест жизненного цикла Linux…#783
Добавлены закреплённый runbook для SSH на Ubuntu и одноразовый smoke-тест жизненного цикла Linux. Он проверяет установку, рендеринг JavaScript, обнаружение артефактов, обновление, доказательства версии и откат без удалённого сервиса.
#783 (задача на GitHub)ИзмененоРаботаетНормализация импортированных данных аналитики и поиска для соединения со сканами (#781).#781
#781 (задача на GitHub)evidence-normalizeполностью офлайн читает переданный экспорт CSV, XLSX или JSON либо сохранённый конвертseohead.provider-evidence.v1и создаёт версионированный документseohead.normalized-evidence.v1по необязательному манифестуseohead.evidence-mapping.v1. Для каждого поля сохраняется происхождение (из конверта, заявлено или неизвестно): источник, идентичность отчёта, период, часовой пояс, атрибуция, поисковая система, покрытие сбора и привязка к URL. Измеренный0остаётся нулём, а отсутствующие строки, пустые ячейки, формулы, скрытые значения, периоды без сбора и неудачный или пропущенный сбор явно помечаются как недоступные.evidence-joinсоединяет нормализованные данные со сканом, аудитом или списком страниц по строгой политике ключейexternal_join.v1, допуская только явные послабления. Совпавшие, только по скану и только внешние записи, а также несоединимые популяции сохраняются на заявленной детализации. Коллизии ключей сообщаются, а не размножают строки.--compareс заявленной политикой добавляет чистое решение compatible, incompatible или unknown по периоду, границе часового пояса, идентичности, атрибуции, поисковой системе и детализации. Он также сообщает пригодность измеренных нулевых квадрантов для последующей когортной работы. Ограниченные источники держат строки и идентификаторы внутри приватного локального артефакта и возвращают только счётчики.ДобавленоРаботаетОфлайн-опыт готовности провайдера: ссылки на учётные данные без секретов и явные#780
состояния доступа…
Добавлен офлайн-опыт готовности провайдера: ссылки на учётные данные без секретов, схемы маршрутов операций, метаданные квот и приватности и явные состояния доступа к цели. Сам факт наличия учётных данных не подтверждает разрешение.
#780 (задача на GitHub)ИзмененоРаботаетКоманда
seohead watchрасширена до наблюдателя проекта только для чтения с навигацией#775по находкам…
Команда
#775 (задача на GitHub)seohead watchрасширена до наблюдателя проекта только для чтения: навигация по сохранённым находкам, подробности доказательств, состояние сохранённых представлений и проверки, а также явно ограниченные уведомления о входящих в MCP.ДобавленоРаботаетДобавлена авторизованная синтетическая доставка отчётов с устойчивыми квитанциями#773
идемпотентности…
Добавлена авторизованная синтетическая доставка отчётов с долговечными квитанциями идемпотентности и безопасным при повторе поведением после перезапуска.
#773 (задача на GitHub)ИзмененоРаботаетНеподтверждённые заявки на доставку сохраняются после выхода процесса или некорректного#773
подтверждения документа. Автоматическая повторная загрузка не происходит, если приём не удалось установить.
#773 (задача на GitHub)ИзмененоРаботаетПредпросмотр отчётов измеряется по сохранённым доказательствам: размер, дайджест#772
источника…
Предпросмотр отчётов измеряется по сохранённым доказательствам: отрисованный размер, дайджест источника, счётчики популяций, покрытие и профиль. Отсутствующие рендереры и слишком большие входы сообщаются до отправки. Бюджет JS мастера в режиме thorough приведён в соответствие с общим контрактом очереди.
#772 (задача на GitHub)ИзмененоРаботаетТочные подтверждённые идентичности отправки бота сохраняются при сбоях очереди и#771
владения, доверенные обновления дедуплицируются, а статус, отмена, восстановление и доставка изолируются по инициирующему актору и чату. Одинаковые намеренные повторные запуски остаются отдельными заданиями.
#771 (задача на GitHub)ИсправленоРаботаетПосле перезапуска сервиса восстанавливается последнее подтверждённое задание актора и#771
чата. Поведение отмены и повторного запуска после нового подтверждения сохраняется, а неподтверждённый черновик не возобновляется.
#771 (задача на GitHub)ДобавленоРаботаетПакет доказательств по обзору ПО для self-hosting, юридической и закупочной проверки#761
(#761)
Добавлен пакет доказательств по обзору ПО для self-hosting, юридической и закупочной проверки (#761).
#761 (задача на GitHub)scripts/generate_review_pack.pyсоздаёт и проверяет версионированный инвентарь зависимостей и лицензий: один профиль на каждую группу установки, с разрешёнными версиями и источниками лицензий, измеренными в окружении генерации. Требования, исключённые маркерами, не удовлетворённые спецификацией и не установленные, записываются, а не отбрасываются. Документ происхождения релиза связывает собранные дистрибутивы с тегом и ревизией исходников из встроенного манифеста сборки, аSHA256SUMS.txtпокрывает всё перечисленное. Генерация отклоняет тег, который не совпадает сpyproject.toml. Проверка перепроверяет форматы и записанные хэши, заново распаковывает каждый дистрибутив, чтобы сверить его встроенный манифест, имя и версию из имени файла и поляNameиVersionв собственном*.dist-info/METADATAилиPKG-INFOсpyproject.toml, а не доверяет записи. Сканирование по маркеруSEOHEAD_REVIEW_CANARY_*подтверждает, что файлы пакета и диагностика не содержат подложенных учётных данных или маркеров клиентов. CI на каждом запуске пересоздаёт и проверяет пакет с одноразовым тегом, а релизный воркфлоу проверяет его и прикладывает к настоящему релизуv*.ДобавленоРаботаетДобавлен
docs/SOFTWARE_REVIEW.md: карта исходящих endpoint и потоков данных…#761Добавлен
#761 (задача на GitHub)docs/SOFTWARE_REVIEW.md: карта исходящих endpoint'ов и потоков данных. Для каждой функции указано, к чему она обращается, что отправляет и является ли вызов необязательным. Документ описывает границу локального и удалённого режимов, хранение учётных данных и артефактов, статус телеметрии, безопасность и сопровождение, а также порядок проверки изменений релиза. Установка и развёртывание не дублируются: документ ссылается на runbook (#783, #787).ДобавленоРаботаетОфлайн-проверка ёмкости и контрольных сумм Google Sheets перед полными локальными#760
BI-пакетами
Добавлена офлайн-проверка ёмкости и контрольных сумм Google Sheets перед выгрузкой полных локальных BI-пакетов. Она не делает запросов к Google и не записывает в таблицы.
#760 (задача на GitHub)ДобавленоРаботаетЯвный транспорт замены Google Sheets по белому списку с соответствием листов по датасетам…#760
Добавлен явный транспорт замены Google Sheets по белому списку: соответствие листов датасетам, ограниченная промежуточная запись с чтением обратно и одна атомарная публикация только значений, которая сохраняет ID существующих листов.
#760 (задача на GitHub)ИзмененоРаботаетПромежуточная запись Google Sheets фиксируется до создания удалённых листов; потерянный#760
ответ begin сверяется…
Промежуточная запись Google Sheets фиксируется контрольной точкой до создания удалённых листов. Если ответ на begin потерян, он сверяется по детерминированным идентификаторам промежуточных листов, и только после этого выполняется повтор.
#760 (задача на GitHub)ИзмененоРаботаетСохраняются типизированные числовые и логические значения и разреженные ответы Google;#760
дубли отклоняются…
Сохраняются типизированные числовые и логические значения и разреженные ответы Google. Дубли целей листов и расхождение контракта датасета отклоняются, восстановление привязывается к точной настроенной цели, а промежуточная запись остаётся доступной для продолжения после исчерпания квоты. Рост целевой сетки учитывается в бюджете до атомарной замены, а количество строк, не подтверждённое при прерванном запуске, сообщается явно.
#760 (задача на GitHub)ИзмененоРаботаетПолные привязанные к исходникам групповые сопутствующие данные проверяются до записи в#760
место назначения, сохраняются вместе с выбранными находками, а ссылки на членство, существующие только локально, раскрываются в квитанциях назначения и книги. При этом не утверждается, что сопутствующие данные загружены.
#760 (задача на GitHub)ИзмененоРаботаетБольшие наборы записей XLSX в
scan-exportделятся на детерминированные нумерованные#759листы с контрольным листом Partitions, который сохраняет число строк. Раньше экспорт падал на лимите Excel на количество строк в листе.
#759 (задача на GitHub)ИзмененоРаботаетЛисты Findings и Pages в
report-buildделятся по лимиту Excel и выводят хэшированный#759индекс…
Листы Findings и Pages в
#759 (задача на GitHub)report-buildделятся по лимиту строк Excel, и создаётся хэшированный.xlsx.index.jsonс точными диапазонами записей, исходной популяцией, ссылками на выборку и покрытие. При перехваченной ошибке записи предыдущий отчёт сохраняется, а временные потоковые файлы очищаются при прерывании.ИзмененоРаботаетXLSX отказывается от ячеек длиннее 32 767 символов до того, как библиотека их обрежет.#759
Метаданные листа Summary защищены от внедрения формул. Некорректные строки сохранённого аудита отклоняются до того, как неполный экспорт сможет выдать себя за успешный. Полные CSV и JSON и ограниченная политика обзора PDF по-прежнему доступны.
#759 (задача на GitHub)ДобавленоРаботаетОграниченная выгрузка выбранных CSV для BI с точным учётом исходных, выбранных и#759
пропущенных строк…
Добавлена ограниченная выгрузка выбранных CSV для BI с точным учётом исходных, выбранных и пропущенных строк, сохранённым покрытием источника, потоковыми хэшами и индексом соответствия диапазонов CSV и листа XLSX. Ячейки Excel, которые превышают лимит, падают до обрезки, а прерванный вывод не помечается как завершённый.
#759 (задача на GitHub)ИзмененоРаботаетПолные неизменяемые строки покрытия проверок сохраняются рядом с выгрузками выбранных#759
находок BI, включая причины пропущенных проверок. Точный выбор находок поддерживается по сегменту области сканирования.
#759 (задача на GitHub)ДобавленоРаботаетОфлайн-диагностика сканирования для сохранённых нативных сканов и артефактов прежних#758
запусков…
Добавлена офлайн-диагностика сканирования для сохранённых нативных сканов и артефактов прежних запусков: ограниченные доказательства решений, понятные объяснения и доступ к CLI и MCP только для чтения. Отдельная команда и инструмент экспорта с маскировкой данных включаются явно.
#758 (задача на GitHub)ДобавленоРаботаетДобавлены версионированные представления находок проекта с закрытыми фильтрами,#757
сортировкой по серьёзности…
Добавлены версионированные представления находок проекта: закрытые фильтры, сортировка с учётом серьёзности, выбор столбцов и ограниченная постраничная навигация. При убывании серьёзности критические находки идут первыми, при возрастании — от уведомлений к критическим. CLI, MCP, отчёты и будущая навигация в терминале могут использовать одно и то же представление только для чтения, не меняя исходные доказательства, оценку, задачи и покрытие.
#757 (задача на GitHub)ДобавленоРаботаетПланирование локального монитора, выключенного по умолчанию, с явными бюджетами#756
инкрементальных и полных обновлений…
Добавлено планирование локального монитора, выключенного по умолчанию, с явными бюджетами инкрементальных и полных обновлений, отказом при перекрытии, заявками на восстановление, неизменяемым происхождением данных наблюдений, сохранением частичных результатов, дедуплицированными оповещениями и уведомлениями о восстановлении. Монитор не запускает ни таймер, ни сканирование, ни канал доставки.
#756 (задача на GitHub)ДобавленоРаботаетЯвный внедряемый адаптер доставки сервисом для сохранённых полных уведомлений монитора.#756
Адаптеру нужны авторизованное назначение, привязанное к проекту, и долговечное хранилище квитанций. Транспорт, аккаунт, таймер или назначение по умолчанию не включаются.
#756 (задача на GitHub)ИзмененоРаботаетЗаявки мониторинга, покрытие, происхождение кэша и доставка сделаны устойчивыми к#756
перезапуску
Заявки мониторинга, покрытие, происхождение кэша, производные доказательства восстановления и необязательная доставка сервисом устойчивы к перезапуску.
#756 (задача на GitHub)ДобавленоРаботаетЯвный одноразовый сборщик монитора с арендой по времени и кэшированными сохранёнными#756
доказательствами…
Добавлен явный одноразовый сборщик монитора с ограничением аренды по времени, кэшированными сохранёнными доказательствами и квитанциями доставки только локально.
#756 (задача на GitHub)ДобавленоРаботаетДобавлены
verify-fixes/seo_verify_fixesдля ограниченной повторной проверки#755выбранных URL по сохранённым ID находок, представлению верификации или явному списку URL…
Добавлены
#755 (задача на GitHub)verify-fixes/seo_verify_fixesдля ограниченной повторной проверки выбранных URL: по сохранённым ID находок, представлению верификации или явному списку URL. Проверка использует записанную политику сканирования, пишет отдельный артефакт верификации и отчёт без перезаписи существующих файлов и различает статусы: исправлено, сохраняется, изменилось и не поддаётся проверке. Существующий аудит «после» можно проверить без сетевого доступа, только если у него есть отдельный UUID скана и более позднее записанное время наблюдения. Непроверенные данные и сигналы по всему сайту никогда не помечаются как исправленные.ИзмененоРаботаетНативное сканирование URL может отбирать найденные маршруты по расширению конечного имени#749
файла до запросов и по фактическому
#749 (задача на GitHub)Content-Typeответа до разбора или хранения тела. Оба этапа фильтрации фиксируют свои решения и сохраняют данные о ссылках, статусах, заголовках и редиректах. Метаданные отфильтрованного HTML явно помечаются как неизмеренные. Скрипты и таблицы стилей выбираются независимо и имеют собственные бюджеты по размеру.ИзмененоРаботаетЕсли тело HTML недоступно, находки на его основе теперь сохраняют явно пропущенное#749
покрытие…
Если тело HTML недоступно, находки, которые строятся на нём, теперь сохраняют явно пропущенное покрытие, а не принимают значения парсера по умолчанию за чистый результат или за наблюдаемое отсутствие метаданных.
#749 (задача на GitHub)ДобавленоРаботаетДобавлены проверяемые исключения по шаблонам URL для находок после анализа.#748
Подавленные находки остаются в JSON аудита и в экспорте report-build вместе с сработавшим правилом и причиной. Итоги активных находок, оценка и список задач отражают заданную политику. Нативные артефакты сканирования сохраняют политику для офлайн-пересчёта; число правил и длина полей ограничены.
#748 (задача на GitHub)ДобавленоРаботаетДобавлен
scan-export(seo_scan_export): офлайн-экспорт данных сканирования только для#747чтения…
Добавлен
#747 (задача на GitHub)scan-export(seo_scan_export): экспорт данных сканирования только для чтения, без сети, по версионированному контрактуscan_export.v1. Он читает проверенный артефактscan.v1в SQLite илиaudit.jsonиз SF Analyzer и пишет CSV (отдельный файл на каждый тип записей плюс манифест), XLSX (книга только для записи), потоковый JSON-конверт или XML по документированной схеме. Каждый результат содержит происхождение данных, число экспортированных строк, статистику запуска и явное покрытие: какие проверки выполнялись, были пропущены, отключены или остались неучтёнными. Ни один выбор полей это покрытие не убирает.--recordsи--fieldsдают проверяемую выборку по записям страниц, ссылок и находок; неизвестные типы записей или имена полей отклоняются до создания любого выходного файла. Отсутствующие значения остаются явными (JSONnull, XMLstate="absent", CSV/XLSX\N), а не превращаются в выдуманные нули. XML формируется как сериализация с корректным экранированием UTF-8; внешний XML, DTD, таблицы стилей и сущности никогда не разбираются. Защита от внедрения формул в CSV/XLSX сохранена. XLSX отказывается от переполнения строк, столбцов и текста ячеек, а не обрезает их. Ошибка сериализации не оставляет правдоподобного частичного файла.ИзмененоРаботаетВ
crawl-siteдобавлена опциональная ограниченная проверка записанных внешних ссылок:#746
#746 (задача на GitHub)discovery.external.crawlзапускает отдельный этап после того, как закрылась внутренняя очередь. Каждый уникальный целевой URL запрашивается один раз, в рамках собственных бюджетовexternal_checks.max_targets/max_hosts/max_requests/max_depth/max_redirects, без рекурсивного обхода внешних хостов. Результаты (получено, ошибка, заблокировано, пропущено с указанием правила, по которому отказано) дописываются вexternal_checks.jsonlв каталоге запуска, сохраняют происхождение от исходной страницы и переживают возобновление без повторного открытия израсходованных бюджетов. Покрытие отражается вdiscovery.external_checksотдельно от полноты внутреннего сканирования. Требуетdiscovery.external.store; на нативном маршруте SQLite (--scan-out) отклоняется по имени, пока этот сборщик не получит такой этап.ДобавленоРаботаетДобавлена явная проверяемая политика HTTP-прокси для нативного сканирования: страниц,#745
sitemap, ресурсов и закреплённого браузера…
Добавлена явная проверяемая политика HTTP forward-прокси для нативного сканирования: она действует на запросы страниц, sitemap, ресурсов и закреплённого браузера. Маршрут каждого запроса записывается с маскировкой чувствительных данных.
#745 (задача на GitHub)ИзмененоРаботаетЭтап рендеринга в нативном сканере теперь выбирает браузер через конфигурацию, а не#744
жёстко зашитый Chromium.
#744 (задача на GitHub)rendering.browser.engineвыбираетchromium(по умолчанию),firefoxилиwebkitчерез тот же защищённый путь Playwright. Неизвестное имя отклоняется при проверке настроек, а не при запуске. Если запрошенный движок не установлен, сканер выдаёт ошибку зависимости с решением (playwright install <engine>), а не тихо переходит на Chromium. Ограничение Firefox соблюдается честно: он отклоняетrendering.browser.mobile_emulation(is_mobileтам не поддерживается), а независимыйrendering.browser.touch_emulation(has_touch) по-прежнему передаётся в контекст. Пробы и полный рендер используют одну действующую конфигурацию, поэтому паттерн никогда не эскалируется браузером, отличным от того, который дал доказательства.ИзмененоРаботает
rendering.browser.viewport_widthиrendering.browser.viewport_heightдобавляют#744произвольные размеры вьюпорта рядом с существующими пресетами
#744 (задача на GitHub)desktopиmobile. Пресеты по-прежнему определяют профиль так же, как раньше. Пара задаётся только целиком и ограничена диапазоном от 1 до 16384 px. Пользовательская пара заменяет только размеры пресета и не включает эмуляцию мобильного устройства или касаний: эти флаги оператор задаёт явно.ИзмененоРаботает
rendering.browser.page_concurrencyограничивает число запросов браузера в полёте при#744эскалации…
#744 (задача на GitHub)rendering.browser.page_concurrencyограничивает, сколько запросов браузера могут выполняться одновременно при эскалации, отдельно отspeed.concurrency, который по-прежнему управляет вежливостью HTTP-сканирования. Значение по умолчанию 1 сохраняет последовательное поведение и вообще не создаёт пул. При значении больше 1 пробы и рендеры работают в ограниченном пуле воркеров, а все решения, фиксации и записи в SQLite остаются в потоке оркестратора в порядке отправки. Дедлайн рендера, бюджет URL и политики «выборочно» и «полностью» работают и при параллельности. Остановленная партия дожидается уже начатых страниц и не запускает новые. Прерванные или упавшие воркеры не оставляют после себя живых потоков, страниц, контекстов или браузеров.ИзмененоРаботаетВыбранный движок, его фактически сообщённая версия, эффективный вьюпорт и заданная#744
параллельность страниц…
Выбранный движок, фактически сообщённая им версия, эффективный вьюпорт и заданная параллельность страниц записываются в манифест сканирования, в отпечаток и в данные о происхождении каждого отрендеренного документа, включая неудачные попытки: там фиксируется запрошенное, но успешный рендер не выдумывается. Оба пути эскалации учитывают настройки: каталоговое сканирование и нативное сканирование в SQLite. Кандидаты ссылок из рендера попадают в очередь через существующую дедупликацию, когда включён
#744 (задача на GitHub)rendering.rendered_links.crawl.ДобавленоРаботаетДобавлены опциональные проверки канонической политики для заданных шаблонов пагинации и#727
фильтров в аудит по экспорту SF и нативному сканированию…
Добавлены опциональные проверки канонической политики для заданных шаблонов URL пагинации и фильтров в конвейеры аудита по экспорту SF и нативного сканирования. Правила пагинации поддерживают цели «сама страница», «первая страница» или «посадочная страница»; правила фильтров — «сама страница» или «посадочная страница». Если политика не задана или цель отсутствует в данных сканирования, это остаётся неизмеренным. Проверки статусов ответа целевых страниц остаются отдельными.
#727 (задача на GitHub)ДобавленоРаботаетДобавлены возобновляемые архивы GSC Search Analytics в общем локальном SQLite-хранилище#718
истории провайдеров…
Возобновляемые архивы GSC Search Analytics добавлены в общее локальное SQLite-хранилище истории провайдеров и доступны единообразно через
#718 (задача на GitHub)gsc-archiveиseo_gsc_archive. Офлайн-статус, явная подготовка, ограниченный сбор и проверенные снимки используют одно ядро.ИзмененоРаботаетСохраняются происхождение провайдера и движка и допускающие пустые значения метрики, в#718
очередь попадают только непокрытые диапазоны…
Сохраняются происхождение провайдера и движка и допускающие пустые значения метрики. В очередь ставятся только непокрытые диапазоны доступности. Паузы из-за квот и ограниченные повторы временных ошибок фиксируются.
#718 (задача на GitHub)ДобавленоРаботаетДобавлена единая версионированная локальная SQLite-история GA4, Метрики, GSC (веб-запросы#716
и страницы) и Yandex Webmaster…
Добавлена единая версионированная локальная SQLite-история ежедневных данных GA4, Метрики, GSC (веб-запросы и страницы) и Yandex Webmaster. Замена дня атомарна, а покрытие явно отмечается: запрошено, пусто, частично, ошибка и отставание.
#716 (задача на GitHub)ДобавленоРаботаетДетерминированная ограниченная синхронизация, офлайн-статус и экспорт JSON/CSV через#716
общий CLI и локальный MCP…
Детерминированная ограниченная синхронизация, офлайн-статус и экспорт JSON/CSV доступны через общий CLI и локальный MCP, включая аддитивность метрик и консервативные метаданные часового пояса. Учётные данные и данные провайдеров в репозитории не хранятся.
#716 (задача на GitHub)ИзмененоРаботаетРежим A для SF теперь проверяет запрошенные возможности экспорта установленного CLI и#715
требует полный свежий набор экспорта до анализа. Происхождение полного профиля фиксирует проверенный манифест экспорта и считанную обратно скорость сканирования. Явное ограничение скорости срабатывает до запуска сканирования, если базовый конфиг отсутствует или некорректен.
#715 (задача на GitHub)ИзмененоРаботает
metrika-report(seo_metrika_report) иMetrikaClient.report(): отказ Reporting API#714«Query is too complicated» теперь повторяется по срезам по календарным месяцам с паузой 5–15 с. Срез, который всё ещё отказывает, отправляется повторно с выборкой при
#714 (задача на GitHub)accuracy=0.1. Объединяются только метрики, которые заведомо аддитивны на непересекающихся периодах (ym:s:visits,ym:s:pageviews). Запрос с метриками уникальных посетителей, процентами, средними значениями или непроверяемыми метриками отклоняется до первого запроса среза, а не возвращает неверную сумму. Срезы объединяются по мере поступления под одним глобальным лимитом строк, который ограничивает и загрузку. Когда лимит исчерпан, оставшиеся части не запрашиваются, а их диапазоны дат перечисляются вsplit.unfetched. Срез, остановленный на полпути, указывает свой диапазон там с пометкойpartial. Значенияtotal_rows/totalsза весь период остаются неизвестными, если незапрошенные периоды делают их невычислимыми, а возвращённое окно помечается как частичное. Объединённые ответы заново применяютsortвызывающего (по измерениям и метрикам или умолчание API: первая метрика по убыванию), а окноoffset/limitберётся из общего объединённого набора. Поля выборки отражают то, что API фактически сообщил (sampled, худшееsample_share). Срез, который их не сообщает, оставляет значение за весь период неизвестным:nullв ответе CLI/MCP, а не выдуманныйfalse.contains_sensitive_data— логическое «или» по срезам,min/maxпересчитываются по объединённым строкам. Отсутствующие или некорректные ячейки метрик и итоги помечают тело какincomplete, а не читаются как ноль. Блокsplitсохраняет запрошенные и вычисленные периоды, использованный часовой пояс, а также точность, попытки, отброшенные строки и метаданные выборки по каждому срезу. Если часть не удалась, ответ называет завершённые диапазоны и исчерпанные значения точности. Относительные даты (today,NdaysAgo) вычисляются вtimezoneзапроса или в часовом поясе счётчика (time_zone_name, иначе его смещение в минутах), но никогда не по дате хоста. Период, который нельзя сопоставить с датами (сокращение вродеmonth), всё равно повторяется и выбирается с выборкой до того, как ошибка вернётся вызывающему. Явныйaccuracyучитывается во всех документированных формах (low/medium/high/fullили числовая доля, например"1"): значение выше последней выборки сохраняет запаснойaccuracy=0.1, а уже более низкая настройка вызывающего (lowили доля не выше него) сохраняется и не повышается. Каждый отправленный запрос, включая отклонённый запрос на весь диапазон, попадает в журнал расходов.ИзмененоРаботаетYandex Webmaster: операция
indexingтеперь читает реальный эндпоинт v4#713
#713 (задача на GitHub)/indexing/samplesвместо несуществующего/search-urls. Новаяbroken_links_samplesчитает/links/internal/broken/samples. Постраничная выборка соблюдает документированный лимит размера страницы для каждого эндпоинта (500 для запросов, 100 для списков примеров), а не отправляетlimit=500везде (#713).ИзмененоРаботаетПостраничная выборка Yandex Webmaster теперь проверяет документированные
countи форму#713списка…
Постраничная выборка Yandex Webmaster теперь проверяет документированное поле
#713 (задача на GitHub)countи форму списка каждой страницы, включая случай, когдаcountменьше числа возвращённых строк. На каждой странице запрашивается не больше оставшегося бюджета строк, поэтому обрезка поmax_rowsне может незаметно превратиться в ложныйcomplete. Одиночная непостраничная выборка отдаётreturned/truncatedкак ограниченный срез. Статусpartialставится всякий раз, когда остаются непрочитанные строки. Некорректные страницы вызывают ошибку вместо ложного пустого полного результата (#713).ИзмененоРаботаетRender-check использует доверие платформы и явно выбранный CA, воспроизводит закреплённые#709
POST-подзапросы и сообщает об ошибках проверки сертификата без подробностей транспорта.
#709 (задача на GitHub)ИзмененоРаботаетРаспознаётся ошибка проверки TLS закреплённого прокси-транспорта, а явное доверие к CA#709
фикстуры проверяется…
Распознаётся ошибка проверки TLS закреплённого прокси-транспорта. Явное доверие к CA фикстуры, повтор POST, ограничения размера ответа и отказ для приватных целей проверяются через собственный синтетический перехватчик CONNECT, без изменения доверия платформы.
#709 (задача на GitHub)
3 октября 2026 г.
5 добавлено8 изменено1 исправленоДобавленоРаботаетДобавлен
crawl-importдля явно сопоставленных CSV-пакетов сторонних сканеров.#819Идентичность внешнего источника, покрытие по полям, повторные наблюдения и недоступные данные сохраняются в
#819 (задача на GitHub)third_party_crawl.v1. Результат не считается нативным сканированием или аудитом SF.ДобавленоРаботаетДобавлен опциональный транспорт удалённого браузера Playwright с явными проверками адреса#808
и версии, безопасными состояниями ошибок и без отката к локальному запуску. Локальный рендеринг по умолчанию не меняется.
#808 (задача на GitHub)ДобавленоРаботаетДобавлены ограниченные детерминированные read-only Python-запросы: кратчайший наблюдаемый#805
путь и входящие ссылки по сохранённым ссылкам скана…
Добавлены ограниченные детерминированные read-only Python-запросы кратчайшего наблюдаемого пути и входящих ссылок по сохранённым ссылкам скана, с идентификатором записи скана для каждого перехода и явным покрытием частичного графа.
#805 (задача на GitHub)ИзмененоРаботаетРегрессионный тест маршрутизации провайдерского workflow приведён в соответствие с#779
исправленным контрактом Arsenkin Wordstat…
Регрессионный тест маршрутизации провайдерского workflow приведён в соответствие с исправленным контрактом запроса частотности Arsenkin Wordstat (#720, #779).
#779 (задача на GitHub)ДобавленоРаботаетДобавлен
docs/PROVIDERS.md: сгенерированная матрица возможностей провайдеров и#779специализированных workflow…
Добавлен
#779 (задача на GitHub)docs/PROVIDERS.md, сгенерированная матрица возможностей провайдеров и специализированных workflow (#779, эпик #753). Документ строится по живому реестру провайдеров и курируемому каталогу workflow вseohead/core/provider_matrix.pyчерезscripts/generate_provider_matrix.py. Для каждого workflow он фиксирует поставляемые команды, авторизацию, стоимость и квоты, класс приватности, ограничения и запасной вариант на CSV черезprovider-join. Статусы различают «поддерживается», «частично», «не поддерживается» и «не проверено». Ни один заявленный провайдер не помечен как проверенный вживую, явно неподдерживаемые задачи перечислены по названию, а первый релиз выбран поэтапно без утверждения, что покрыты все сервисы. Расхождения между закоммиченным документом и реестрами ловятtests/test_docs_drift.pyиtests/test_provider_matrix.py.ИсправленоРаботаетИсправлен
keywords-exact/seo_keywords_exact: он не мог вернуть результат, так как#720задача создавалась для несуществующего инструмента Arsenkin…
Исправлен
#720 (задача на GitHub)keywords-exact/seo_keywords_exact, который никогда не мог вернуть результат: задача создавалась для несуществующего инструмента Arsenkin с именемkeywords_frequency, поэтому каждый вызов получал404 WRONG_TOOL. Точный!Wтеперь уходит в инструментwordstatсtype=1, массив фраз передаётся вqueries, а регион — одним элементом списка.ИзмененоРаботаетДля
!Wзапрашивается селекторoveral: значенияwsв Arsenkin — разные операторы…#720Запрашивается селектор
#720 (задача на GitHub)overalдля!W: значенияwsв Arsenkin — разные операторы.base— широкий (WS),quoted— фраза в кавычках («WS»),overal— точная словоформа (!WS), которую запрашивает!W, аexact— строгий порядок ([!WS]).ИзмененоРаботаетПеред отправкой удаляется пунктуация, которую провайдер отвергает: фраза с
/или…#720Перед отправкой удаляется пунктуация, которую провайдер не принимает: одна фраза с
#720 (задача на GitHub)/или кавычками отклоняла весь пакет с ошибкой422 JSON_VALIDATION_ERROR. Переписанные фразы возвращаются в полеcleaned, чтобы было видно, какие из них измерены в другой форме.ИзмененоРаботает
frequenciesвозвращается как{phrase: {"base": N, "overal": N}}рядом с сырым ответом#720провайдера. Фраза, по которой результат содержит только другие регионы, опускается и перечисляется в
#720 (задача на GitHub)warnings, а не получает чужие цифры.ДобавленоРаботаетДобавлен ограниченный доступ к Topvisor только для чтения через общий CLI и обработчик#719
MCP: учётные данные хранятся в центральных файлах, пагинация явная, операций с платными проверками нет.
#719 (задача на GitHub)ИзмененоРаботаетУстаревший блок
sources.gscвsources-doctorприведён в соответствие с#717
#717 (задача на GitHub)provider_status.gsc:readyи новое полеcomponentsтеперь берутся из тех же компонентов учётных данных (OAuth-токен, постоянный грант или сервисный аккаунт), а не только из файла с токеном. Поэтому настроенный сервисный аккаунт больше не выглядит как «GSC не настроен». Компонент сервисного аккаунта теперь сам проверяет JSON-документ: приватный обычный файл, ограниченный размер, типservice_account, точный URI токена Google и обязательные поля. Оба блока doctor сообщают безопасное значениеservice_account_statusиз перечняmissing,unsafe_file,too_large,unreadable,malformed_json,unsupported_shapeилиconfigured_unverified. Благодаря этому слишком большой, нечитаемый или некорректный файл отличается от настроенного, но непроверенного, и при этом его содержимое не раскрывается.ИзмененоРаботаетАртефакты сканирования
crawl-siteтеперь проставляютfinished_atиfinished, когда#712каждая принятая строка очереди достигла конечного состояния…
Артефакты сканирования
#712 (задача на GitHub)crawl-siteтеперь проставляютfinished_atи статус жизненного циклаfinished, когда каждая принятая строка очереди достигает конечного состояния, включая запуски с частично сохранёнными данными:crawl_partialуже перечисляет пропущенные наблюдения, поэтому опустевшая очередь больше не выглядит как прерванный сбор вscan-status,scan-listили истории (#712). Явно остановленный запуск (прерванный до принятия работы, отменённый или остановленный circuit breaker по ошибкам) сохраняет статусinterruptedи записанную причину даже после опустошения очереди, в том числе черезresume_or_finalize, поэтому пути остановки никогда не получают ложную отметку времени завершения.ИзмененоРаботает
duplicate-check --scanиboilerplate-report --scanтеперь потоково читают сохранённый#710корпус вместо падения на обычных сайтах…
#710 (задача на GitHub)duplicate-check --scanиboilerplate-report --scanтеперь потоково читают сохранённый корпус вместо падения на сайтах обычного размера: дедлайн открытия и проверки скана рассчитывается по размеру артефакта, а каждое чтение документа получает собственный дедлайн. Корпус на 1,5 тыс. страниц больше не заканчивается статусомinterrupted. Бюджет входных байтов корпуса считает то, что анализатор действительно сохраняет: извлечённый Markdown для дубликатов и один дайджест на страницу для шаблонного текста, а не размер сырого HTML. Достижение границы корпуса даёт частичное покрытие с точными счётчиками prepared/eligible и указанием границы, которая остановила чтение (#710).ИзмененоРаботаетMetrika
report()иby_time()теперь локально отклоняютoffset < 1сValueError,#707вместо того чтобы передавать его в Reporting API, который на
#707 (задача на GitHub)offset=0отвечает HTTP 400. Новые офлайн-тесты закрепляют нумерацию с единицы вmetrika-report,seo_metrika_reportиprovider-collectaggregate_report, а также проверяют, что условия остановки постраничной выборки (total_rows,ROW_CAP) учитывают строки, пропущенные при нестандартномoffset(#707).
2 октября 2026 г.
1 добавлено2 измененоИзмененоРаботает
metrika-traffic-pdfна macOS: Chrome записывает PDF и продолжает работать; браузер#731теперь запускается без ожидания…
#731 (задача на GitHub)metrika-traffic-pdfна macOS: Chrome записывает PDF и продолжает работать. Браузер теперь запускается без ожидания и останавливается после проверки PDF.ИзмененоРаботаетYandex Webmaster:
user_idопределяется по токену; новые операции только для чтения…#713Yandex Webmaster:
#713 (задача на GitHub)user_idопределяется по токену. Новые операции только для чтения:summary,diagnostics,sqi_history,search_history,query_history,in_search_history,events_history,indexing_history,important_urls,broken_links_history,external_links_history. Появилисьparamsдля дат и индикаторов, а также постраничная выборка списков запросов и примеров сканирования (#713).ДобавленоРаботаетНовый технический скилл
traffic-report: клиентский месячный или годовой отчёт поМетрике, Webmaster и Search Console (конверсии, учтённые как визиты, проверки целей, товары, портрет покупателя, правила слайдов).
1 октября 2026 г.
1 добавлено1 измененоДобавленоРаботаетДобавлен
metrika-traffic-pdf(seo_metrika_traffic_pdf): статический трафик-отчёт#731формата A4 в альбомной ориентации…
Добавлен
#731 (задача на GitHub)metrika-traffic-pdf(seo_metrika_traffic_pdf): статический отчёт по трафику формата A4 в альбомной ориентации, оформленный как аналитическая панель и построенный по Яндекс Метрике. Сбор данных и отрисовка разделены на два этапа. Сбор читает Reporting API (около 40 бесплатных запросов только для чтения) и формирует один документseohead.metrika-traffic/1. Он включает девять KPI-карточек: пользователи, визиты, просмотры, страниц за визит, визитов в день, показатель отказов, средняя длительность визита, доля посетителей с двумя-тремя визитами и доля новых посетителей. Для каждой есть изменение относительно предыдущего периода такой же длины и тех же дат годом раньше. Также включены ежедневная динамика; окна 3/6/12 месяцев против предыдущих окон; поисковые системы, города, страны, устройства, возраст, пол, главные посадочные страницы и поисковые фразы; все каналы трафика. Рендеринг превращает документ в самодостаточный HTML с встроенными SVG-диаграммами и печатает его в PDF через установленные локально Chrome, Edge или Chromium (SEOHEAD_CHROMEзадаёт путь вручную). Брендинг (название, цвета, стек шрифтов, текст логотипа) и подписи на английском или русском — входные параметры; строки запросов Search Console можно добавить как необязательную страницу. Атрибуция по умолчанию идёт по последнему значимому источнику (ym:s:lastSignTrafficSourceи его измерения системы и фразы), именно её показывает интерфейс Метрики. Атрибуция по последнему клику отличается от неё на несколько процентов и задаётся явно черезattribution=last_click. Каждый запрос передаётoffset=1, потому что API считает строки с единицы. Отсутствующие данные остаются видимыми: каждый блок несётok,unavailableилиskippedс причиной; изменение без базы сравнения равноnull, а не нулю; при отсутствии браузера HTML остаётся, а PDF помечается как пропущенный; существующие файлы вout_dirзаменяются только приoverwrite=true.ИзмененоРаботаетОтчёты Метрики начинаются с
offset=1: Reporting API нумерует с единицы, и каждый запрос…#707Отчёты Метрики начинаются с
#707 (задача на GitHub)offset=1: Reporting API нумерует с единицы, а каждый запрос сoffset=0получал HTTP 400 (#707, #728, #729).
26 сентября 2026 г.
1 добавленоДобавленоРаботаетНативное сканирование добавляет
HEADING_SKIPдля скачков уровней H1–H6 в области#725основного контента…
Нативное сканирование добавляет
#725 (задача на GitHub)HEADING_SKIPдля скачков уровней H1–H6 в указанной области контента. Заголовки шапки, подвала, навигации, боковой панели, а также явно скрытых или закрытых диалогов исключаются, чтобы элементы шаблона не создавали ложную иерархию. В запусках Screaming Frog только по экспорту проверка помечается как недоступная.
23 сентября 2026 г.
1 измененоИзмененоРаботаетПриватные файлы секретов принимаются в Windows, где нет битов прав POSIX, и добавляется#708
скрипт согласия в браузере…
Приватные файлы секретов принимаются в Windows, где нет битов прав POSIX. Добавлен скрипт согласия в браузере, который сохраняет грант Search Console только для чтения.
#708 (задача на GitHub)
13 сентября 2026 г.
2 добавлено3 изменено2 исправленоДобавленоРаботаетНативные SQLite-записи, история, повторы, снимки, переанализ и публикация проектов теперь#705
работают в Windows…
Нативные SQLite-записи, история, повторы, снимки, переанализ и публикация проектов работают в Windows: блокировки байтовых диапазонов на уровне ОС и портативная проверка свободного места. Синхронизация каталогов POSIX сохранена; в Windows сброс файлов и атомарная публикация доступны, но без гарантии fsync каталога POSIX. Портативные сценарии проверяются в Windows CI и изолированной среде Linux.
#705 (задача на GitHub)ИсправленоРаботаетСканирование HTML в режиме сырого текста остаётся совместимым с версиями Python без новой#705
опции скриптов…
Сканирование HTML в режиме сырого текста остаётся совместимым с версиями Python, в которых нет новой опции скриптов в HTMLParser, включая дистрибутив Windows Python 3.12.
#705 (задача на GitHub)ИсправленоРаботаетУточнены и подкреплены источниками рекомендации Google по структурированным данным и#704
Googlebot, включая доступность FAQ/HowTo и последствия политики структурированных данных.
#704 (задача на GitHub)ИзмененоРаботаетФайлы Sitemap ищутся от корня сайта через
robots.txtс запасным/sitemap.xml…#703Файлы Sitemap ищутся от корня сайта через
#703 (задача на GitHub)robots.txtс запасным вариантом/sitemap.xml, а если все sitemap не раскрылись, это сообщается какok: false.ИзмененоРаботаетНативное сканирование можно возобновить после анонимных cookie, выставленных сервером, с#702
фиксацией новой сессии…
Нативное сканирование можно возобновить после анонимных cookie, выставленных сервером: новая сессия фиксируется без сохранения значений cookie. Сканирования с учётными данными и с постоянным профилем по-прежнему нельзя возобновить.
#702 (задача на GitHub)ИзмененоРаботаетСохранённые сканы задаются через
--scan, встроенный JSON через--input; старые#701варианты…
Сохранённые сканы задаются через
#701 (задача на GitHub)--scan, встроенный JSON через--input. Устаревшие варианты--inputдля пути скана и--json-inputработают ещё один релиз, но с предупреждением.ДобавленоРаботаетДобавлено явное подтверждение, выключенное по умолчанию, для хранения ограниченных#700
анонимных данных с заголовком
#700 (задача на GitHub)Cache-Control: no-store. Тела с учётными данными по-прежнему не сохраняются.
9 сентября 2026 г.
10 добавлено9 изменено2 исправленоДобавленоРаботаетОфлайн-предпросмотр приоритетов проекта и версионированное применение политики по фактам#694
стека…
Добавлены офлайн-предпросмотры приоритетов проекта и явное версионированное применение политики на основе сохранённых фактов стека. Выбор оператора сохраняется, история политики ведётся атомарно, а объяснения приоритетов в читаемых отчётах соответствуют друг другу.
#694 (задача на GitHub)ИсправленоРаботаетУточнены рекомендации по рендерингу JavaScript, canonical, гигиене URL и
notranslate#692без изменения проверок…
Уточнены рекомендации по рендерингу JavaScript, canonical, гигиене URL и
#692 (задача на GitHub)notranslate. Проверки в коде и уровни серьёзности не менялись.- ИсправленоРаботаетАдреса sitemap и robots в фикстуре документации остаются на эфемерном loopback-origin.#690 (задача на GitHub)
ДобавленоРаботаетДобавлено портативное покрытие чеклистом проекта: встроенный каталог, выведенный из#686
исходников, и пользовательские шаблоны…
Добавлено портативное покрытие чеклистом проекта: встроенный каталог, выведенный из исходников, многоразовые пользовательские шаблоны, история определений и доказательств, оптимистичная конкурентная запись, явная проверка вручную и по результатам, а также офлайн-представления «ожидает», «устарело» и «заблокировано», общие для CLI, MCP и отчётов проекта.
#686 (задача на GitHub)ДобавленоРаботаетДобавлена read-only сводка статуса нативного сканирования по популяциям очереди и#685
зафиксированным результатам HTTP…
Добавлена read-only сводка статуса нативного сканирования по популяциям фронтира и зафиксированным результатам HTTP-запросов.
#685 (задача на GitHub)ДобавленоРаботаетДобавлены портативные локальные рабочие пространства проектов с явными состояниями#678
ожидания чеклиста и подготовки.
#678 (задача на GitHub)ДобавленоРаботаетОбзор руководств Google Search Central зафиксирован в репозитории: 175 прочитанных#677
руководств, их метки, исключения, дата снимка и три исправления, к которым он привёл.
#677 (задача на GitHub)ИзмененоРаботаетURL-режим
crawl-siteтеперь по умолчанию пишет нативный SQLite-скан без конфликтов имён#676в каталог вызывающего…
URL-режим
#676 (задача на GitHub)crawl-siteтеперь по умолчанию пишет нативный SQLite-скан без конфликтов имён в каталогscans/вызывающего.--out-dirостаётся явным устаревшим маршрутом для каталога, а список URL на входе и конфигурации кэша live/replay указывают этот маршрут, а не меняют режим сбора молча.ИзмененоРаботаетЧистые сборки дистрибутива теперь встраивают проверенные данные о происхождении нативных#675
SQLite-сканов, если исходный checkout недоступен.
#675 (задача на GitHub)ИзмененоРаботаетНеподтверждённые утверждения о фиксированном 301 (потере сигналов) и категоричном 302#671
(без передачи веса) заменены в скилле аудита…
Неподтверждённые утверждения о фиксированном 301 (потере сигналов) и категоричном 302 (отсутствии передачи веса) в скилле аудита заменены рекомендациями о постоянном или временном намерении и каноническом целевом URL со ссылкой на Google Search Central. Временные редиректы остаются корректными для временных изменений; сам код статуса не измеряет потерю позиций.
#671 (задача на GitHub)ИзмененоРаботает
render-check --viewport mobileтеперь использует один стабильный диагностический#670идентификатор смартфона для сырых и браузерных запросов. Явный
#670 (задача на GitHub)--user-agentдоступен через CLI и MCP, а каждое завершённое или частичное сравнение фиксирует действующий идентификатор и размер viewport.ДобавленоРаботаетДобавлены read-only входы
--scanдля анализа дублей и шаблонного контента по корпусу, с#669покрытием сохранённых тел и происхождением…
Добавлены read-only входы
#669 (задача на GitHub)--scanдля анализа дублей и шаблонного контента по корпусу: с покрытием сохранённых тел и указанием происхождения данных.ДобавленоРаботаетДобавлен сгенерированный каталог входов команд, задокументировано решение по хранилищу#668
сканирования, HTTP-кэша и журнала запусков.
#668 (задача на GitHub)ИзмененоРаботаетКлиентские отчёты в Markdown, CSV, XLSX, DOCX и задачи теперь используют понятные#660
читателю названия находок и сохранённые доказательства воспроизведения вместо идентификаторов реестра и имён коллекторов. Исторические записи без достаточных доказательств прямо указывают на это ограничение, JSON-артефакты аудита не меняются.
#660 (задача на GitHub)ДобавленоРаботаетДобавлена
project-facts: фиксирует факты о стеке проекта после создания, при#648необходимости по одному проходу tech-detect с соблюдением robots…
Добавлена команда
#648 (задача на GitHub)project-facts: фиксирует факты о стеке проекта после создания, при необходимости по одному проходуtech-detectс соблюдением robots.txt. Решения оператора приоритетнее обнаруженных данных. Если определение недоступно или неоднозначно, факт не записывается, а причина указывается.ИзмененоРаботаетREADME начинается с контроллера проекта, Screaming Frog описан как перекрёстная вторая#648
проверка, а не эталон паритета…
README начинается с контроллера проекта, а Screaming Frog описан как перекрёстная вторая проверка, а не как эталон паритета.
#648 (задача на GitHub)ДобавленоРаботаетДобавлен
examples/project-skeletonс инициализированным чек-листом без результатов,#648чтобы
project…Добавлен
#648 (задача на GitHub)examples/project-skeletonс инициализированным чек-листом без результатов:project statusна нём показывает счётчики покрытия вместоnot_initialized, а файл проверяется по актуальному каталогу.ДобавленоРаботаетДобавлены контракты подготовки проекта, доказательств провайдеров, сохранённого корпуса,#354
ограниченного извлечения, доказательств сканирования и workflow/каталога с явными границами сохраняемых доказательств и прогресса.
#354 (задача на GitHub)ИзмененоРаботаетПрофили MCP и обёртки прогресса с сохранением метаданных требуют опционального MCP SDK#354
1.29 или новее…
Профили MCP и обёртки прогресса с сохранением метаданных требуют опционального MCP SDK версии 1.29 или новее.
#354 (задача на GitHub)ИзмененоРаботаетREADME упрощён вокруг сценариев «задача → команда → артефакт», убраны устаревшие
визуальные вставки и маркетинговые счётчики, а ссылки на сгенерированные справочники живого интерфейса сохранены.
ИзмененоРаботаетREADME дополнен практическими сценариями «вход → результат» с соответствующими вызовами
CLI/MCP и точными границами сохранённого корпуса и браузера/провайдеров…
README дополнен практическими сценариями «вход → результат» с соответствующими вызовами CLI/MCP и точными границами сохранённого корпуса, браузера и провайдеров.
8 сентября 2026 г.
8 изменено2 исправленоИзмененоРаботаетДокументация SQLite-артефакта приведена в соответствие с поставляемым нативным телом,#666
историей и контрактами офлайн-переанализа (#666). Таблица полей поздних страниц теперь сверяется с маппингом импортёра: старое наблюдение из JSONL остаётся SQL NULL, а не превращается в выдуманное «чистое» значение.
#666 (задача на GitHub)ИзмененоРаботаетНативные аудиты теперь помечают проверки meta keywords, вторичного canonical, версии HTTP#659
и amphtml как пропущенные, если исходные поля не собирались.
#659 (задача на GitHub)ИсправленоРаботаетПерестаём читать cookie, который сайт выставил как учётные данные оператора, в конвейере#656
JavaScript-рендеринга, и явно сообщаем, когда запуск отбрасывает отрендеренные DOM (#656). Браузер возвращает обратно всё, что ему выставил собственный
#656 (задача на GitHub)Set-Cookieсайта. Поэтому стоило странице выставить сессионный cookie и затем запросить один same-origin подресурс (скрипт, таблицу стилей, изображение — обычная картина веба), как хук запросов рендерера считывалCookie:с провода и сохранял сериализованный DOM страницы какomitted/credentialedпри запуске сhttp.credential_headers = []. Каждый рендер создаёт собственный браузерный контекст, поэтому потеря идёт постранично, а не накапливается: каждая страница, выставившая cookie, теряет собственный DOM, а запуск сообщает о своих страницах, ссылках и счётчиках эскалации так же, как для полного. Значениеcredentials_usedдля отрендеренного документа теперь берётся только из того, что запуск был настроен отправлять:http.credential_headersили постоянный профиль браузера. Именно это уже вычисляетcrawl/sqlite_render.py::_policy_factsи передаёт рендереру. Рендерер строит собственный сетевой клиент без собственных учётных данных, поэтому по проводу добавить было нечего. Сканирование с настроенными учётными данными по-прежнему исключает такие DOM подcredentialed, без изменений, а значение cookie по-прежнему никогда не сохраняется.ИзмененоРаботаетТеперь названы счётчики отрендеренных страниц, которые флаг
partialне может передать…#656
#656 (задача на GitHub)rendered_bodiesв результатеcrawl-siteпоказывает, сколько отрендеренных DOM сохранено, и причину для каждого несохранённого. CLI печатает это рядом со строкой завершения, а не оставляет на флаге возможности, который говорит «partial» и при одном пропущенном DOM, и при всех. Запуск, который ничего не отбросил, ничего дополнительно не печатает. Счётчики читаются из артефакта сканирования, поэтому завершённое сканирование по-прежнему отвечает на тот же вопрос позже.ИзмененоРаботаетСобираем
og:urlпри нативном сканировании вместо того, чтобы помечать каждую страницу#654как лишённую его (#654).
#654 (задача на GitHub)rules.check_ogвключаетog:urlвmissing_tagsстраницы всякий раз, когда поле ложно. При этом нативный путь вообще не читал тег: не былоog_urlвPageRecord, колонкиog_urlвscan_v1.sqlиOG:URLв проекции Internal:All, которую строитcrawl/evidence.py. Колонка существовала только на стороне Screaming Frog, гдеnormalizeвсегда разрешалOG:URL. Поэтому экспорт сайта видел реальное значение, а нативное сканирование того же сайта сообщало о дефекте: неизмеренное поле выдавалось за измеренное, на каждой странице каждого нативного сканирования, независимо от разметки. Теперь тег читается там же, где три других (парсер уже возвращал его какog:url), сохраняется в nullable-колонкеpages.og_url, как и все остальные поздно добавленные колонки, чтобы запись, сделанная до сбора, отличалась от страницы без объявленного тега, и проецируется какOG:URL. Это сторона сбора, а сторона чтения исправлена в #646. Вtests/test_open_graph_seam.pyдобавлен третий тестовый сайт, на страницах которого есть Open Graph, но нетog:title, чтобы находка действительно срабатывала и её список можно было прочитать: одна страница объявляетog:urlи не должна быть названа без него, вторая не объявляет и должна быть. Ключевой тест проверяет обе страницы дважды: один раз по сканированию и один раз по экспорту Internal:All, описывающему те же две страницы, и требует одинакового вердикта. #646 и #654 были двумя путями, которые расходились без теста, охватывающего оба.ИсправленоРаботаетПерестаём читать cookie, который сайт выставил как учётные данные оператора, и явно#647
сообщаем, когда запуск отбрасывает тела (#647). Сканирование использует один HTTP-клиент, а у клиента есть cookie jar: как только любой ответ нёс
#647 (задача на GitHub)Set-Cookie, все последующие запросы уходили сCookie:, а писатель корпуса классифицировал их как аутентифицированные. На публичном сайте сhttp.credential_headers = []иcredentials_acknowledged = falseэто отбросило 33 001 из 40 920 тел страниц, а запуск сообщал о страницах и ссылках так, будто сканирование полное. Всё, что вычисляется по сохранённому HTML этого сканирования (поиск почти-дублей, глубина и число узлов DOM, доля шаблонного контента, структура заголовков в теле, переанализ офлайн), тогда покрывало 7 903 страницы, а все процентные показатели по страницам в том же отчёте покрывали 40 920. Две совокупности были представлены как одна. Захват считается учётным, если запуск был настроен отправлять заголовок учётных данных для этого хоста. Это единственный способ, которым чувствительный заголовок может попасть в запрос, который строит сканер:http.headersотклоняется валидацией конфигурации. Сканирование с настроенными учётными данными по-прежнему исключает такие тела подcredentialed, без изменений.ИзмененоРаботаетНазваны счётчики, которые флаг
partialне может передать…#647
#647 (задача на GitHub)html_bodiesв результатеcrawl-siteпоказывает, сколько загруженных HTML-тел страниц сохранено, и причину для каждого несохранённого. CLI печатает это рядом со строкой завершения, а не оставляет на флаге возможности, который говорит «partial» и при одном пропущенном теле, и при четырёх пятых от всех. Запуск, который ничего не отбросил, ничего дополнительно не печатает. Списки заголовков запроса и ответа после редакции теперь сохраняют названия заголовков, которые редакция удалила, в полеx-seohead-redacted-headers, но никогда не их значения. Раньше два ответа, тела которых обрабатывались по-разному, записывали побайтово одинаковые списки заголовков, поэтому оператор, читающий артефакт, не мог понять, почему тело отсутствует.ИзмененоРаботаетЗаписи changelog вынесены из
CHANGELOG.mdв отдельные файлы на каждое изменение под…#638Записи changelog вынесены из
#638 (задача на GitHub)CHANGELOG.mdв отдельный файл на каждое изменение вchangelog.d/, поэтому pull request больше не конфликтует с каждым другим pull request, влитым раньше (#638). Каждая ветка добавляла запись в начало## Unreleased, и эта одна строка становилась точкой конфликта: девять ручных разрешений на восемь pull request за две сессии, каждое с повторным пушем и новым CI-прогоном, и решение всякий раз было «оставить наш блок, потом их». Конфликт, ответ на который никогда не меняется, не несёт информации и лишь отвлекает от работы. Предложенное в issue исправление через.gitattributes,CHANGELOG.md merge=union, было измерено и отвергнуто ещё до этого. Union-слияние работает построчно: если обе записи содержат одинаковую строку (достаточно пустой строки внутри записи), оно оставляет одну копию и сообщает об успехе, молча удаляя строку другой записи без конфликта и без повода посмотреть. Первый тест с заведомо различными строками прошёл чисто и скрыл это. Обмен громкого конфликта на тихую потерю данных хуже самого конфликта, поэтому выпущено структурное решение.ИзмененоРаботаетФрагмент называется по закрываемому issue (
changelog.d/638.md), ключу, который по#638построению уникален для ветки…
Фрагмент называется по закрываемому issue (
#638 (задача на GitHub)changelog.d/638.md): ключ уникален для ветки по построению. Pull request, закрывающий два issue, пишет два фрагмента, по одному на каждый issue, а изменение, которое ничего не закрывает, пишетno-issue-<slug>.md. Фрагмент содержит запись ровно в том виде, в каком она должна быть в changelog: один или несколько маркеров верхнего уровня с продолжениями строк, без front matter и обёртки. Благодаря этому многоабзацные текстовые записи круглым путём возвращаются побайтово, а не превращаются в однострочники.python scripts/build_changelog.pyсворачивает их в## Unreleasedпри выпуске, упорядочивая по номеру issue, а не по порядку, который вернула файловая система. Флаг--pruneудаляет свёрнутые фрагменты. Сборка заменяет всю область между двумя маркерами-комментариями, а не вставляет в неё, поэтому два запуска дают один и тот же файл, удалялись фрагменты между ними или нет.CHANGELOG.mdсознательно не перегенерируется в каждом pull request: шлюз, который держал бы его постоянно синхронизированным, снова поместил бы обе ветки в один файл и воссоздал бы конфликт, который это устраняет.ИзмененоРаботаетОпасными были шлюзы документации, читавшие
CHANGELOG.md, потому что шлюз, который тихо#638перестаёт что-либо проверять, хуже конфликтов…
Опасными были шлюзы документации, читавшие
#638 (задача на GitHub)CHANGELOG.md: шлюз, который тихо перестаёт что-либо проверять, хуже конфликтов. Оба нашлись и теперь покрывают фрагменты.tests/test_docs_drift.pyдержалCHANGELOG.mdвPUBLIC_MARKDOWN, поэтому шлюз «только английский», шлюз «ссылаются только на существующие команды» и шлюз устаревших счётчиков теперь читают иchangelog.d/*.md. Два шлюза дрейфа счётчиков пропускают фрагмент по той же причине, что и changelog: запись фиксирует то, что было истинно на момент написания.tests/test_doc_counts.pyсознательно исключает changelog из скана живых счётчиков, а его список файлов не доходит доchangelog.d/, и ответ тот же по той же причине.tests/test_doc_commands.py,tests/test_docs_commands_execute.pyиtests/test_examples_gate.pychangelog вообще не читают. Новыйtests/test_changelog_fragments.pyзакрепляет каждый из этих ответов, а также именование фрагментов, детерминированный порядок, идемпотентную сборку и то, что две имитируемые параллельные ветки, каждая добавившая фрагмент, сливаются без конфликта.
Ранее (дата не указана)
23 добавлено30 изменено17 исправленоИсправленоРаботаетПродолжаем снимать отпечаток страницы, если сайт присылает
Set-Cookieбез значения(#651).
Заголовок без пары
name=valueвообще, напримерSet-Cookie: Secure; HttpOnly, которыйemall.byприсылает рядом с двумя корректными cookie, попадал в jar какCookie(name='Secure', value=None), аhttpx.Cookies.__getitem__для него поднимаетKeyError. Поэтомуdict(resp.cookies)падал на имени, которое выдал собственный итератор отображения.tech-detectзавершался с кодом 1 и голой строкойerror: 'Secure'без JSON в stdout для страницы, загруженной успешно. MCPseo_tech_detectпередавалKeyErrorвызывающему, аsite-auditмолча возвращался без всего раздела технологий. Теперьdetect_techобходит cookie jar. Имя без значения сохраняется с пустым значением, а не отбрасывается, потому что несколько отпечатков (BITRIX_SM_GUEST_ID,craft_session,wfvt_) совпадают только по имени cookie, и отбрасывание потеряло бы этот сигнал. Но такой cookie никогда не нормализуется молча в обычный. Имена попадают вmalformed_cookiesи упоминаются в находке, поэтому битый заголовок, присланный сайтом, остаётся фактом о сайте. Ответ только с корректными cookie не меняется и возвращает пустой список.ИзмененоРаботает
render-checkснова измеряет сжатые сайты, а не объявляет их сломанными (#650).Закреплённый маршрут рендера читал исходник через нераскодированный поток httpx и передавал эти байты Playwright вместе с
content-encodingисточника.route.fulfillникогда не применяет content-coding к переданному телу, поэтому Chromium разбирал gzip какtext/htmlи строил DOM из сжатого потока: ни title, ни h1, ни canonical, ни ссылок, а размер отрисовки был равен размеру передачи. Каждый сайт, сжимающий HTML, а таких почти все, получалok: false, reason: incomplete_render, и сообщение винило рендер, советуя--wait domcontentloadedили больший--timeout, хотя рендер завершился нормально. Дляseohead.techотчёт показывал 22 435 байт против 121 793 сырых, теперь показывает 123 048 с правильным title и 31 ссылкой. Маршрут теперь читает раскодированную сущность, убираетcontent-encodingиз того, что пересылает (content-lengthи так убирался как hop-by-hop, поэтому Playwright указывает длину того тела, которое реально получил), и запрашивает у источника только те кодировки, которые этот клиент умеет декодировать, а не пересылает приглашение Chromium кbrиzstd. Кодировка, пришедшая нераскодированной, прерывает запрос и называет себя, потому что пропуск её дальше молча воспроизвёл бы дефект. Ограничение по байтам теперь считает раскодированные байты, то есть тело, которое видит рендерер: бомба сжатия раньше проходила лимит в сжатом виде.ИзмененоРаботаетЧитаем Open Graph при нативном сканировании по ключу, который парсер действительно
записывает (#646).
parse_htmlсохраняет каждый тег под полным именем свойства,{"og:title": ...}, как сказано в его docstring, аcrawl/collect.pyзапрашивал из того же словаря"title","description"и"image".dict.getкаждый раз возвращалNone, поэтомуog_title,og_descriptionиog_imageбыли пустыми на каждой странице каждого нативного сканирования, когда-либо запущенного. В запуске, где проблема обнаружилась, из 40 920 страниц ни на одной не было ни одного из них, хотя на сайте страницы публикуют Open Graph. Это обращение базового правила репозитория: неизмеренное поле читалось как измеренное. Проблема распространялась, потому чтоcrawl/evidence.pyпроецирует эти колонки вOG:Title,OG:DescriptionиOG:Imageкадра Internal:All. Поэтому проверка на нативном сканировании видела пустоту, а на экспорте Screaming Frog того же сайта видела реальное значение. Честностьcheck_ogскрывала повреждение, а не показывала его: раз ни одна колонка OG нигде не заполнялась, проверка пропускалась, и сайт с Open Graph аудитировался так же, как сайт без него. Парсер не изменён, сдвинута только сторона чтения. Новыйtests/test_open_graph_seam.pyсканирует два loopback-тестовых сайта и проводит значение от парсера черезpages.jsonlи таблицуpagesартефакта сканирования до колонок кадраOG:*. Третий сайт без Open Graph удерживает различие между «пусто, потому что отсутствует» и «пусто, потому что не прочитано». Форма ключа парсера закреплена в том же файле. Сбой был в том, что два корректных модуля расходились в имени ключа, и ни один тест не охватывал оба.ИзмененоРаботаетОтвечаем на вопрос «хорошо ли перелинкован сайт и где перелинкован плохо», расширив
реестр с 157 до 161 проверки и добавив скилл internal-linking (#634)…
Отвечаем на вопрос «хорошо ли перелинкован сайт и где перелинкован плохо»: реестр расширен с 157 до 161 проверки, добавлен скилл
internal-linking(#634). Части уже существовали: каждое ребро с позицией, якорем и флагом nofollow в таблицеlinks, а такжеORPHAN_PAGE,INLINK_BOILERPLATE_ONLY,LOW_LINK_SCORE. Но ничто не превращало их в ответ о графе. Аудит 40 920 страниц часами выдавал неверный главный вывод: 66% sitemap считались недоступными по внутренним ссылкам. Эта цифра получалась вычитанием числа URL сканирования из числа URL sitemap, то есть измеряла «краулер туда не дошёл». Обход 5 252 235 рёбер артефакта от главной страницы дал доступность 91,9%. Настоящий дефект был в глубине: 23 742 страницы, 58% сайта, находились дальше десяти кликов от главной, а самая глубокая — на расстоянии 3 005, потому что архив устроен как связный список ссылок «следующая запись», а не как дерево. Главным выводом аудита теперь печатается глубина клика.summary.internal_linkingсодержит гистограмму, максимум, разбиение на достижимые и недостижимые, внутренние рёбра по позиции на странице и число рёбер, повторяющих другие рёбра.audit.mdвыводит это рядом с общей сводкой здоровья. Обход начинается с URL, с которого реально стартовало сканирование, а не сpages.crawl_depth. Этот столбец фиксирует, где краулер случайно достал URL, а при сканировании по sitemap для большинства страниц там стоит 0, поэтому обход из него описывал бы другое место. Если стартовый URL не записан и больше одной страницы претендует на глубину 0, измерение не запускается и называет причину.ИзмененоРаботаетЧетыре проверки читают эти числа.
DEEP_CLICK_DEPTHсрабатывает на индексируемой странице, кратчайший путь к которой от стартового URL превышаетthresholds.click_depth_max(по умолчанию 10; каждая находка называет использованное число).DUPLICATE_INTERNAL_LINKсрабатывает на странице, которая указывает один и тот же адрес назначения с одним и тем же якорем больше одного раза. На описанном выше сайте повторами были 509 744 из 1 134 307 рёбер, то есть 44,9%. Это была одна шапка, выведенная дважды, причём вторую копию удалял JavaScript: дефект шаблона, поиск которого потребовал рукописного скрипта.LINK_INSIDE_HEADINGиIMAGE_LINK_WITHOUT_TEXTтребуют того, чего не может вместить регион страницы, где стоит ссылка: цепочку предков якоря и его содержимое. Поэтому нативное сканирование теперь записывает небольшой ограниченный по размеруlink_placement_jsonдля каждой страницы рядом с outline заголовков. Обе проверки пропускаются по имени на экспорте Screaming Frog, а не проходят чисто на пустых данных.ИзмененоРаботаетПравила честности, которым следует остальной анализатор, действуют везде.
Ребро без записанной позиции учитывается как
unclassifiedи никогда не сворачивается вcontent.link_position.classifyпо умолчанию выключен, поэтому такое состояние относится к каждому ребру. Запуск в этом состоянии должен читаться как «никто не смотрел», а не как сайт, у которого все ссылки в тексте. Позиция, отсутствующая в распределении, описывается как «здесь не классифицировано ни одно ребро», а не как регион, которого нет на сайте: правила проверяются по порядку, и меню внутри<header>сначала совпадает сnav. Частичное сканирование снимает вердикт по глубине клика независимо от того, сработал он или нет: непрочитанная граница может содержать более короткий путь. Проверка, молча не нашедшая ничего, читалась бы как «все страницы в пределах порога».ИсправленоРаботаетПерестаём считать проверку, зависящую от требования, пройденной, если её никто не
выполнял (#635).
H2_MISSINGсрабатывает только тогда, когда конфигурация задаётrequirements.require_h2, а по умолчанию это false, поэтому в обычном запуске его ветка недостижима. Однако это не оставляло следа: покрытие относило проверку к молчаливым, то есть к корзине «прошла по каждой странице и ничего не нашла», а читателю сообщалось, что сайт прошёл проверку, которую никто не запускал. В аудите, где это обнаружилось, 61% страниц сайта не имели H2 вообще, а 5 066 из них были длиннее 800 слов, так что проверка сработала бы тысячи раз. Теперь она объявляется пропущенной по имени, с причиной, которая называет настройку, выключившую её. Ответ теперь звучит так: «не оценено, и вот как это оценить», а не молчание.require_canonicalустроен так же и получает такую же обработку. Его значение по умолчанию true, поэтому он пока не давал неверного показания, но теперь и не может начать.ИсправленоРаботаетИсправляем заголовок backlog задач, который читался как «Audit Tasks — None» для любого
аудита, у которого запуск не записал проект (#640).
render_tasks_mdстроил заголовок черезsrc.get("project", "site"). Но"project"всегда присутствует как ключ в блокеsourcebacklog: он задаётся при сборке изrun.get("project"), и запуск без проекта сохраняет там значениеNone, а не оставляет ключ отсутствующим. Значение по умолчанию уdict.getсрабатывает только для отсутствующего ключа, но не для ключа со значениемNone. Нативное сканирование и переанализ не задаютproject, поэтому каждый backlog из них получал в заголовке буквальное слово «None». Теперь заголовок падает назад черезor, который ловит и сохранённыйNone, и берётstart_urlилиsourceсайта до того, как сдаться. Порядок тот же, что уже использовалseohead.reports.facts.crawl_domainдля определения имени сайта по блокуrun. Функция теперь экспортируется и переиспользуется здесь вместо нового изобретения, поэтому backlog по аудиту без проекта называет настоящий сайт, а не слово «site». Вseohead.reports._normalize_sf_audit(reports/__init__.py) была та же скрытая форма строкой ниже (run.get("project") or ""). Она уже защищалась от сохранённогоNone, но запасным значением был пустой домен, а не URL, который запуск тоже знает. Поэтому заголовок «SEO Audit: » в docx и md оставался пустым в тех же ситуациях. Теперь он падает назад через ту же логикуcrawl_domain.ИзмененоРаботаетЧитаем outline заголовков как последовательность и как карту страницы, расширив реестр с
155 до 157 проверок (#632)…
Читаем outline заголовков как последовательность и как карту страницы: реестр расширен с 155 до 157 проверок (#632). Восемь существующих проверок заголовков оценивают их как множество. Они могут сказать, что на странице один H1 и четыре H2, и больше ничего. Поэтому страница, где порядок в DOM
H2, H2, ..., H1, H2, проходила все восемь, и страница, все H2 которой были пунктами меню в шапке, тоже. На живом сайте это нашлось в шаблоне статьи: восемнадцать заголовков стояли перед собственным H1, и отчёт по заголовкам считал их чистыми. Не хватало не правила, а доказательств. Вpagesхранилисьh1,h1_2иh2, то есть три строки без порядка и места. Теперь нативное сканирование записывает весь outlineh1–h6в порядке DOM: каждый заголовок с уровнем, текстом и регионом страницы, в новой nullable-колонкеheading_outline_json. ПроверкиHEADING_BEFORE_H1иHEADING_IN_PAGE_CHROMEчитают его. Регион использует таксономию, которую уже применяет классификация ссылок (nav,header,sidebar,footer,content,other), поэтому «в шапке» означает о заголовке то же, что уже означает о ссылке. Заголовок, который не совпал ни с одним правилом позиции, сравнивается с областью содержимого только тогда, когда документ её назвал:<main>,[role=main],<article>или настроенный селектор. Если корень содержимого падает назад на весь<body>, называть заголовок «content» значило бы не больше, чем «где-то на странице». Поэтому регион записывается как неизмеренный, а страница называется среди пропущенных проверок запуска с этой причиной. Её не отмечают ни чистой, ни дефектной. Порядок не требует региона, поэтомуHEADING_BEFORE_H1по-прежнему отвечает для таких страниц. Экспорт Screaming Frog outline не содержит вовсе, и обе проверки там пропускаются по имени.ИсправленоРаботаетСохраняем завершённый сбор, когда аудит после него падает (#627).
Нативное сканирование живого сайта потратило двадцать минут, собирая 600 страниц в артефакт
--scan-out, а затем напечаталоerror: 'rel_next_2'.str()уKeyErrorвозвращает только ключ. Ни фазы, ни трассировки, ни признака того, что все собранные страницы лежат в файле полными и пригодными для переанализа. Сбор фиксирует свои строки и закрывается до начала аудита, поэтому всё, что возникает после этой точки, — поведение анализатора, а не сканирования. Неожиданное исключение теперь называется по фазе, сообщает тип исключения вместе с сообщением и указывает на сохранённый артефакт и команду его переанализа, точно так же, как уже делал путь для слишком большого аудита. Запуск сообщаетaudit_available: falseс этой причиной, а не завершается из-за исключения.crawl-siteвыходит с кодом 2, как и для противоречия в лог-скане. Ноль означал бы «аудит прошёл и что-то нашёл», а единица означала бы «команда ничего не выдала», и ни то ни другое неверно для сканирования, чьи данные сохранились. СамаKeyErrorне воспроизвелась: та же команда на том же сайте на текущем main завершилась успешно. Поэтому изменилось то, что происходит при падении аудита, но не то, что вызвало именно это падение.ИсправленоРаботаетПерестаём терять аудит завершённого сканирования из-за фиксированного 30-секундного
бюджета проверки при повторном открытии (#631).
NativeScan.open()читает заголовок нативного скана черезinspect(). Тот же вызов запускаетPRAGMA quick_checkиPRAGMA foreign_key_checkпо всей базе. Это реальная проверка безопасности, но её стоимость растёт вместе с артефактом, а бюджет был фиксирован. Сканирование на 3,5 часа и 40 920 страниц закончило сбор всего, что собиралось, но аудита не выдало вовсе: повторное открытие получившегося артефакта на 1 ГБ требовало примерно 48 секунд проверки при бюджете, зафиксированном на 30. Хуже того, сбой не давал повода подозревать бюджет. Срабатывание дедлайна приходило из SQLite как голоеsqlite3.OperationalError("interrupted"), и оно оборачивалось дословно вcannot inspect native scan: interrupted, неотличимое от реально повреждённого файла. Исправлено оба. Бюджет по умолчанию теперь выводится из размера артефакта: минимум 30 секунд для маленьких файлов плюс щедрая надбавка на байт, заметно ниже измеренной скорости проверки примерно 22 МБ/с. Это потолок на случай зависшего чтения, а не целевая производительность. Явныйtimeout_secondsот вызывающей стороны по-прежнему его переопределяет. Срабатывание дедлайна теперь поднимаетScanError, который называет бюджет, прошедшее время и размер артефакта. Так оператор отличит медленный большой файл от повреждённого, а не будет считать «interrupted» ошибкой со своей стороны.ДобавленоРаботаетДобавлен
crawl-site --resume <scan.sqlite>(#619).NativeScan.resume_snapshot(), таблицаresume_stateи писатель, который её заполняет, существовали со времени проектирования артефакта сканирования.crawl_to_scanуже умел продолжать существующий файл, но только для вызывающей стороны, которая воспроизводила исходные эффективные настройки побайтово, а ни один интерфейс этого не предлагал. Указание--scan-outна прерванный артефакт с любым изменённым флагом отклонялось как несоответствие конфигурации. На практике прерванное сканирование (6 516 из 34 635 страниц чужого сайта) приходилось начинать с нуля.--resumeпринимает только артефакт и ничего больше. Стартовый URL и полная эффективная конфигурация читаются обратно из файла, потому что на них построен сохранённый фронтир. Любой другой флаг, формирующий сканирование, переданный вместе с ним, отклоняется, а не применяется. Скан, записанный другой сборкой, сохранённый для другого стартового URL, уже завершённый, выведенный из переанализа или сканированный с заголовками учётных данных, которые он может хранить только в редактированном виде, отклоняется по имени, по одному только файлу, до отправки хотя бы одного запроса.crawl-siteтеперь также печатает в stderr одну строку при выходе: сканирование завершилось или остановилось раньше, почему, и как продолжить. Исключение составляют бюджеты по URL и по длительности, которые resume читает обратно и поэтому не может обойти. В этом случае строка говорит именно об этом, а не предлагает бессмысленную команду.run.crawl_resumedостаётся постоянной записью. Возобновлённое сканирование тестового офлайн-сайта загружает каждый URL ровно один раз в двух процессах вместе и даёт аудит, идентичный аудиту непрерванного сканирования по каждому полю, кроме этого одного.ИсправленоРаботает
render-checkбольше не объявляет нерендеренную страницу чистой, и перестаёт отбрасыватьсвидетельства сырого HTML при неудачном рендере (#642).
В
render-checkдва следствия защиты из #623, оба вrender.py. Первое: рендер, который истёк по таймауту на вехе load, откатывается к чтению DOM наdomcontentloaded. Сам по себе это верно, но если к этому моменту ни один скрипт не выполнился, отрендеренный DOM совпадал с сырым HTML. Компаратор ничего не находил, и запуск сообщалok: True,js_dependent: Falseи единственную находку «Raw HTML and rendered DOM are materially equivalent; JavaScript rendering does not determine SEO-visible content» с уровнем notice. Это было сказано о странице, которую никто не рендерил.wait_reachedзаписывал правду, но отчёт site-audit переносит в отчёт только текст находок, поэтому правда до читателя не доходила. Теперь запуск, который откатился к более ранней вехе, говорит об этом в самом списке находок, не выдаёт общего «всё в порядке» и сообщаетjs_dependent: None: запуск не знает ответа, а неFalse. Это срабатывало при умолчании--wait load, а не только при явно заданномnetworkidle. Второе: защита возвращала единственное утверждение «сравнение недоступно» раньше, чем ветка пустой оболочки, а ранний возвратrender_checkне включал ключempty_shellвообще. Поэтому пустая точка монтирования SPA, которуюdetect_empty_shell()читает из сырого ответа сервера и которой не нужен браузер, терялась вместе с провалившимся рендером. Пустая оболочка SPA как раз та страница, у которой рендер и истекает по таймауту, поэтому находка пропадала именно там, где была нужна. Находка, выведенная из сырой половины, теперь переживает незавершённый рендер. Подавляются только находки, выведенные из отрендеренной половины. В сканировании проба рендера, не пришедшая ни к какому вердикту, попадает вpatterns_unprobedс причиной (канал из #626), а не засчитывается как паттерн, измеренный и признанный не требующим рендера.ИзмененоРаботаетНечитаемый robots.txt сообщается как факт о сайте, а не как внутренняя ошибка (#629).
EMPTY_ROBOTS, заглушка, которую_fetch_robotsвозвращает на каждом пути, где robots.txt не удалось прочитать, всё ещё имела форму разобранного robots из времён до того, как парсер научился групам и sitemap. Путь успеха возвращает формуparse_robots, и это единственная форма, которую принимает контекстrobots_summaryартефакта сканирования. Поэтому в режиме--scan-outсканирование падало сnative parsed robots summary is invalidкаждый раз, когда robots.txt был недоступен, отвечал 429 или 5xx, перенаправлял на другой хост, уходил в цикл, превышал бюджет переходов или отдавал тело неtext/plain. Сюда же входил обычный 404: это не ошибка, а случай RFC 9309 «ограничений нет» и самый частый из семи. За одной строкой терялись оба задокументированных исхода. Отсутствующий robots.txt теперь снова даёт сканирование без ограничений, а недоступный останавливает запуск с заметкой, которая называет один из шести способов сбоя. Устаревший режим сканирования по каталогу этого не замечал, потому что старые ключи никто не читает. Обнаружено на живом сайте, чей robots.txt перенаправляет с 302 на endpoint синхронизации cookie для любого User-Agent, который он не узнаёт.ИсправленоРаботаетИсправляем
escalate(), который считал неудавшуюся пробу рендера признаком того, что«паттерн не требует рендеринга» (#626).
escalate()берёт один URL на шаблон-паттерн, чтобы решить, нужна ли для этого паттерна более полная загрузка с JavaScript-рендерингом. Но если все пробы паттерна не смогли выполниться вовсе (сбой запуска браузера, таймаут или незавершённый рендер, обычные режимы сбоя реального сканирования),for/elseвсё равно записывал паттерн как проверенный. В итоге он не эскалировался и не попадал в список паттернов, которые запуск не смог оценить. Это переворачивало базовое правило проекта: отсутствующие или неизмеренные данные не должны читаться как чистые. Паттерн, о котором ничего не узнали, молча сканировался статически и выглядел так же, как измеренный и признанный не требующим рендера. ТеперьEscalationResultсообщает такой паттерн вpatterns_unprobedвместе с уже отслеживаемыми там паттернами, которых коснулся дедлайн. Причину сбоя пробы он записывает в новое полеpatterns_unprobed_reasons, поэтому отчёт может написать «этот паттерн не оценён», а не подразумевать, что он оценён. Паттерн хотя бы с одной успешной пробой не меняется. Это влияет только на случай, когда все пробы паттерна вернулиok: False.ИсправленоРаботает
render-checkбольше не выдаёт незавершённый рендер за дефект сайта (#623).Когда рендер не завершился, отрендеренный снимок приходил без title, без
h1, без canonical, с нулём ссылок и пятой частью байтов сырого ответа. Компаратор читал эту пустоту как свидетельство о сайте. Он выдавал «the title changes after JavaScript» про title, который рендер не прочитал, и «the canonical is injected by JavaScript» про canonical, которого он не видел. В одном живом аудите это дало четыре уверенные ложные находки подряд, каждая из которых отправляла разработчика искать несуществующий баг JavaScript. Теперь пара проверяется до сравнения. Если сырой ответ содержит ориентиры, а отрендеренный документ не содержит ни одного из них и весит долю от сырого размера, проверка возвращаетok: falseсreason: "incomplete_render", именованной причиной, в которой указаны оба размера в байтах, и оба снимка для осмотра. Находок нет, аjs_dependent: null, а неfalse, потому что запуск не знает ответа.site-auditзаписывает это вsummary.tools_failed, куда и попадает непроверенная проверка. Обнаружение намеренно узкое. Один уцелевший ориентир или отрендеренный документ, не меньший половины сырого ответа, сравниваются как раньше. Страница без title и без ссылок с обеих сторон измеряется и признаётся просто пустой, а не непроверенной. Title, который скрипт действительно переписывает, по-прежнему даёт свою находку. Стратегия ожидания тоже справляется с обычной причиной. Сайт, чьи долгие опросы аналитики, чата или рекламных скриптов не дают ему уйти в network-idle, раньше целиком срывал проверку под--wait networkidle. Теперь он откатывается к чтению DOM наdomcontentloadedбез второй навигации.wait_reachedзаписывает, из какой вехи реально взят снимок, плюс короткая пауза для отложенных скриптов. Страница, у которой DOMContentLoaded так и не сработал, остаётся сбоем рендеринга, а не незавершённым рендером.ИзмененоРаботаетДобавлена живая строка прогресса для
crawl-site(#619, половина про прогресс).Нативное сканирование печатало эффективную скорость запросов и затем не выводило ничего до конца. На сайте в 34 000 страниц единственный способ понять, что оно ещё работает, — смотреть, как растёт файл скана в
ls -la. Теперь строка обновляется на месте в TTY и показывает число загруженных страниц, известные на данный момент URL, процент от этого набора, текущую скорость запросов за скользящее окно, прошедшее время и размер артефакта скана, если он пишется через--scan-out. Намеренно не подразумевается общий объём, который нельзя знать. Краулер сам открывает свою работу, поэтому знаменатель равенfetched + queued, ограниченному бюджетом URL. Он помечен какknown, а неtotal, а строка заголовка, выводимая один раз, говорит, что фронтир ещё растёт и процент не является оценкой времени завершения. Нераспознаваемая скорость выводится какrate n/a, а не как0.0 req/s. Обе цифры берутся из собственных структур сканирования. Для SQLite-скана это тот же запросresume_snapshot, по которому ведётся цикл сбора, поэтому на экране находится то, что артефакт содержит в этот момент, а не параллельный счётчик, который может разойтись с ним. Не-TTY (канал, лог-файл, CI) получает простую строку каждые 30 секунд вместо перерисовки через возврат каретки. Новый флаг-q/--quietотключает и строку прогресса, и стартовую строку скорости, оставляя JSON-результат в stdout нетронутым.ИзмененоРаботаетЗакрыты три строки пагинации, которые оставил #385, реестр расширен с 152 до 155 проверок…
Закрыты три строки пагинации, которые оставил #385: реестр расширен с 152 до 155 проверок.
PAGINATION_MULTIPLEиPAGINATION_URL_NOT_IN_ANCHORсообщают о странице, которая объявляет двух разных преемников, или о странице, чей объявленный URL не является также якорем на той же странице. Преемники сравниваются после нормализации URL, то есть по той же идентичности, что и половина с якорями. Поэтому/blog/page/2и/blog/page/2/из двух плагинов считаются одним преемником, записанным дважды, а не неоднозначной серией.PAGINATION_URL_NOT_IN_ANCHORтребует полного списка ссылок страницы и читает для этого экспорт All Inlinks.PAGINATION_MULTIPLEэтого не требует. Теперь он сначала читает более лёгкие колонки вхожденийrel="next" 2/rel="prev" 2изInternal:All, так же какCANONICAL_MULTIPLEуже отвечает поCanonical Link Element 2. All Inlinks служит запасным вариантом только для профиля, чейInternal:Allзаписан без этих колонок.PAGINATION_SEQUENCE_ERRORсообщает о разрыве в последовательности номеров страниц, которой серия иначе следует, по собственной оговорке issue. Серия может начинаться не с единицы, шаг не считается разрывом, а серия, чьи URL не содержат номера страницы, объявляется непроверенной, а не оценивается по нумерации, которую пришлось бы выдумать. Каждая непроверенная серия называется среди пропущенных проверок запуска с причиной, верной именно для неё. Шаг, цикл, слишком короткая серия для прогона и нечитаемый номер страницы — четыре разных утверждения, и три из них описывают серии, чьи URL все содержат номер. Счёт ведётся по серии, а не по запуску, поэтому обычная форма WordPress (первая страница на безномерном/blog/, остальные на/blog/page/N/) не исчезает за одной оцениваемой серией на другом участке того же сканирования.ДобавленоРаботаетДобавлен шлюз покрытия вердиктов проверок (#98):
test_check_producer_gate.pyдоказывал,что каждый ID проверки зарегистрирован и каждая функция проверки диспатчится…
Добавлен шлюз покрытия вердиктов проверок (#98).
test_check_producer_gate.pyдоказывал, что каждый ID проверки зарегистрирован и каждая функцияcheck_*диспатчится, но ничего не говорил о том, был ли вывод проверки когда-либо доказан истинным на разметке, где дефект действительно есть, и молчал на разметке, где его нет. Именно этот пробел позволил #94, #95 и #96 пройти все существующие тесты и при этом ложно срабатывать на живых сайтах.test_check_verdict_coverage.pyсканируетtests/структурно (через AST, а не по фиксированному списку мест вызова) и проверяет обе половины для каждой проверки. Сборка падает для любой проверки, добавленной в реестр без двустороннего теста или без названного и обоснованного исключения. Из 152 проверок реестра 88 уже имели двустороннее доказательство. Новыйtest_check_verdict_gaps.pyзакрывает ещё 22 дешёвых для тестирования пробела, которые выявило сканирование: длину и дублирование title и description, дубли H1, наличие H2, гигиену URL, директивные и разметочные проверки, коды ответа и две проверки нативных экспортов-фильтров. Оставшиеся 64 названы, а не скрыты, в храповикеKNOWN_UNCOVEREDшлюза. Список нужно сокращать по мере появления покрытия. Он не должен расти, чтобы пропустить проверку, добавленную после появления этого шлюза.ИсправленоРаботаетИсправлен дефект выбора группы в robots.txt, из-за которого пустое значение
User-agentотменяло политику сайта по умолчанию (#566). Голая строка
User-agent:или строка, чьё имя бота съел встроенный комментарий (User-agent: # old bot rule), разбиралась в пустой токен._rules_forобрабатывал его как любое другое буквальное имя. Пустой токен — это префикс нулевой длины у каждого агента, поэтому он совпадал со всеми. Так как он считался именованным совпадением, он перебивал настоящую группуUser-agent: *файла для каждого краулера, которого файл не упоминает. Поэтому robots.txt, чьим единственным содержательным правилом былоUser-agent: * / Disallow: /, читался как полностью доступный для обхода. Это касалось и отчёта о доступе AI-ботов, и собственного гейта выборки живого краулера, который вызывает тот жеis_allowed. Теперь пустые токены пропускаются, поэтому такая группа никого не называет, и применяется групповой wildcard. Наиболее конкретная именованная группа по-прежнему побеждает. А robots.txt, не называющий никого, по-прежнему означает, что всё разрешено.ИсправленоРаботаетИсправлены четыре дефекта выбора экспорта и проверки запуска, которые позволяли аудиту
показать результат, который он не мог подтвердить (#209, #210, #215, #216). Сопоставитель
internal_allтребовал только токен имени файлаinternal. Поэтому частичная вкладка Internal по типу, напримерinternal_html.csv, без всех не-HTML строк, удовлетворяла обязательный мастер-экспорт Internal:All без предупреждения об отсутствии мастера. Теперь он также требуетall.discover_exportsдля логического ключа при двух подходящих файлах брал первый по порядку сортировки имён. Например, при наличииinternal_all.csvиinternal-all.csvс разными строками второй молча отбрасывался, и в метаданных запуска не было ничего, что указывало бы на выбор. Теперь функция выбрасывает исключение и называет каждого кандидата.run_sfбрал самую новую подпапку с временной меткой в--out, независимо от момента создания. Поэтому перезапуск, который завершался с кодом 0 и ничего не писал (сбой запуска, который Screaming Frog не отмечает ненулевым кодом), мог вернуть экспорты предыдущего вызова как свежие. Теперь сравнение ведётся со снимком, сделанным до старта процесса, и запуск громко падает, если ничего нового не появилось.build_commandдобавлял--auth-configтолько тогда, когда файл профиля уже существовал. Поэтому опечатка или удалённый путь молча запускали неавторизованное сканирование. Для необязательного умолчательногоseospiderconfigэто уместно, а для профиля, который вызывающая сторона явно запросила, нет. Теперь отсутствующий явныйsf_cli.auth_configвыбрасывает исключение до запуска Screaming Frog.ИсправленоРаботаетИсправлены два дефекта извлечения содержимого в
seohead/checks/parser.py(#138, #140).collapse_whitespaceдекодировал HTML-сущности повторно, сверх единственного декодирования, которое lxml-парсер BeautifulSoup выполняет для каждого значенияtag.get_text()илиtag.get(attr). На обычной разметке это был безвредный холостой ход. Но на странице, чья CMS или импорт уже дважды экранировали сущности, а такой артефакт встречается часто, это превращало явно сломанную кашу сущностей в аккуратный на вид текст и укорачивало отчётную длину ниже того, что реально показывает вкладка браузера или сниппет в выдаче. Из-за этого проверки длины title и description ошибались в обе стороны. Теперь хелпер вообще не декодирует. Кроме того, извлечение ссылок и URL-источников обходило весь документ безусловно. Поэтому<a>или<img>, существующие только внутри инертного<template>, которые по спецификации HTML никогда не входят в отрисованный документ и которые ни браузер, ни краулер не запрашивают без клонирования скриптом, считались реальной ссылкой на странице, иspider.pyих фактически запрашивал. Это тот же класс фантомных URL, что закрыт для<base href>в #4. Оба экстрактора теперь пропускают потомков<template>.<noscript>намеренно оставлен доступным, в отличие от извлечения текста. Это реальная, описанная спецификацией запасная разметка, которую загружает клиент без JavaScript, а также проход поисковых систем без рендеринга. Исключение её скрыло бы от аудитора реально запрашиваемый URL. Подсчёт слов также больше не учитывает текст потомков<svg>и<math>: доступный заголовок спрайта иконок (<title>), текст глифов (<text>), текст глифов и MathML-нотацию. Шапка с двадцатью иконками могла удваивать отчётное число слов относительно реального содержимого. Список исключений теперь находится в одном месте,content_area.TEXT_EXCLUDED_TAGS, и используется обоими текстовыми экстракторами, вместо двух копий, которые уже разошлись.ИсправленоРаботаетСохраняем полные токены
relссылки, её атрибутtargetи исходный href (до разрешения)…Сохраняем полные токены
relссылки, её атрибутtargetи исходный href до разрешения, а также извлекаем элементы<form>: метод, action и наличие поля пароля (#125). Шесть каталогизированных проблем зависели от того, что эти три факта отбрасывались. Речь о небезопасных кросс-доменных ссылках (target="_blank"безrel="noopener"или"noreferrer"), протокол-относительных ссылках (//host/pathдо разрешения), исходящих ссылках на localhost, странице, которая получает одновременно следуемую и nofollow внутреннюю ссылку, небезопасном action формы и форме с паролем, отданной по HTTP. Теперь все шесть соответствуютUNSAFE_CROSS_ORIGIN_LINK,PROTOCOL_RELATIVE_LINK,OUTLINK_TO_LOCALHOST,FOLLOW_AND_NOFOLLOW_INLINKS,FORM_URL_INSECUREиFORM_ON_HTTP_URLв реестре. Проверки форм, localhost и смешения nofollow требуют только тех полей, которые каждое сканирование уже записывало, поэтому эти четыре работают безусловно. Кросс-доменная пара и протокол-относительная пара требуютlink_attributes.capture, которое выключено по умолчанию, потому что дополнительные данные по каждому ребру дали примерно +50% на синтетическом сканировании 3387 страниц по 150 ссылок на страницу: около +95 байт на ребро, +46 МиБ всего, и в основном за счётraw_href. Реестр вырос с 121 до 127 проверок.ИсправленоРаботаетИсправлен молчаливый вывод отчёта без находок для SF Analyzer в
report-build(#151)…Исправлено молчаливое построение отчёта без находок для
audit.jsonSF Analyzer вreport-build(#151). Документированный рецепт,sf run --tasks, переданный вreport-build --format docx,xlsx,csvилиmd, читалfindingsи плоские ключи страниц. Схема SF их не использует: находки лежат вissues, факты страниц вpages[].metrics. Расхождение давало уверенную сводку0/0/0/0для аудита, который нашёл настоящие критические проблемы, и без разделов находок. Теперьbuild_reportраспознаёт и нативную формуseohead.site-audit/1, и форму SF Analyzer. Вторую он нормализует в плоский контракт, который уже понимают четыре человекочитаемых писателя, и только потом рендерит.--format jsonне тронут: он и раньше правильно передавал исходный документ, что и доказало, что данные не терялись. Документ, не подходящий ни под один контракт, отклоняется сok: False, и ошибка называет несоответствие схемы. Он не рендерится как пустой результат. Мёртвое условиеif ... : pass, которое выглядело как проверка, но ничего не делало, удалено.tests/test_docs_commands_execute.pyтеперь проверяет сводку документированного рецепта по собственным итогамaudit.json, а не только код возврата.ИзмененоРаботаетЗакрыты два пробела денежной безопасности в
seohead/data_sources/(#157, #159).geo_guardпроверял только рекомендательную строкуcountry. Поэтомуsearch_volume,keyword_ideas,keyword_difficultyиserpмогли всё равно уйти на живой endpoint DataForSEO дляlocation_code=2643(Россия) или2112(Беларусь), если вызывающая сторона передавала числовой geo-target, но не заполнялаcountry. Теперь шлюз сначала проверяетlocation_code, потому что именно по нему выставляется счёт. Кроме того, сетевое исключение (URLError,TimeoutError,SSLError) во время платного вызова, то есть вpostDataForSEO,/setArsenkin иwordstat.topRequests,wordstat.dynamics,web.searchAsyncв Yandex Cloud, раньше повторяло тот же payload без ключа идемпотентности и логировало только ту попытку, которая в итоге вернула ответ. Ни один из трёх провайдеров не даёт механизма идемпотентности для этих endpoint'ов, поэтому потерянный ответ больше не повторяется. Попытка записывается в журнал расходов (стоимость неизвестна, помеченаattempt_failed: network_error), и вызов падает целиком, а не рискует вторым списанием. Идемпотентные чтения (/checkи/getArsenkin, опрос операций Yandex Cloud) не затронуты и повторяются как прежде.yandex_cloud.WebSearch.search_batchизолирует потерянную отправку внутри своего запроса и не обрывает весь батч.metrika.pyповторяет сетевые ошибки так же, но он не тарифицируется деньгами и не менялся. Если создание экспорта Logs API должно получить такую же обработку по соображениям квот, это вынесено на отдельный шаг.ИзмененоРаботаетЗакрыт DNS-rebinding в
http_client()(#142):pinned_target(), исправление TOCTOU-окнаиз #14, защищал только выборку списком в collect.py…
Закрыт DNS-rebinding в
http_client()(#142).pinned_target(), исправление TOCTOU-окна из #14, защищал только выборку списком вcollect.py. Остальные четырнадцать мест вызова, включая движокcrawl-siteвspider.py, позволяли httpx разрешать DNS второй, независимый раз для открытия сокета. Поэтому злонамеренный резолвер, отвечающий на этот второй запрос иначе, чем проверка защиты, мог привести к169.254.169.254или к любому адресу RFC 1918, независимо от вердикта защиты. Теперьhttp_client()строит каждый клиент на транспорте, который закрепляет соединение за адресом, разрешённым самим транспортом, на первом запросе и на каждом переходе редиректа. Имя хоста сохраняется только для заголовкаHostи TLS SNI. Исправление структурное, а не дисциплина, которую каждый вызывающий должен помнить.SEOHEAD_ALLOW_PRIVATE_NETWORKSиSEOHEAD_ALLOW_PRIVATE_HOSTSне изменены.ИсправленоРаботаетИсправлен контракт кодов выхода CLI/MCP для сбоя, о котором обработчик сообщает сам, и
дополнен SOURCE_FLAGS (#155, #156)…
Исправлен контракт кодов выхода CLI/MCP для сбоя, о котором обработчик сообщает сам, и дополнен
SOURCE_FLAGS(#155, #156). Обработчик, возвращающий{"ok": false, ...}, то есть задокументированный способ слоя инструментов сообщить о сбое загрузки, парсинга или провайдера без исключения, раньше печатал этот JSON и завершался с кодом 0 в CLI. Через MCP он возвращал обычный результат безisError. Поэтому пайплайн, проверяющий$?, или клиент, смотрящий только наisError, не мог обнаружить сбой.cli.pyтеперь выходит с кодом 1 в этом случае. Собственный код 2 уlog-scanдля самопротиворечивого запуска остаётся отдельным задокументированным сигналом, см.docs/USAGE.md.mcp_server.pyподнимаетToolErrorиз общей обёртки_checked(), поэтому клиент видитisError. Обе ветки вызывают одинhandlers.handler_failed(), чтобы два интерфейса не расходились в определении сбоя. Кроме того, вSOURCE_FLAGSдобавлены--phrase,--keywords,--query/--queries,--seed,--counter,--beforeи--after. Каждый из них уже определяет весь вход команды так же, как--url, но отсутствовал в списке. Поэтому построчный цикл по любому из них молча обрабатывал только первую строку. Набор теперь строится функцией_source_flag()в точке объявления каждого флага, а не перечисляется отдельно вручную, и поэтому не может снова разойтись.ИзмененоРаботаетРасширен
docs/scenarios/с десяти цепочек до пятидесяти шести, сгруппированных повопросу, с которым приходит читатель (#120). Какие сценарии существуют, решает карта покрытия, а не вкус. Каждый сценарий объявляет каталогизированные проблемы, которые он решает.
tests/test_scenario_coverage.pyпроверяет, что каждая проблема, которую этот инструмент заявляет как обнаруживаемую, входит хотя бы в один сценарий, что ни один сценарий не называет проблему, которой нет в карте, и что ни один не опускает своих ограничений. Покрыты все 143 обнаруживаемые проблемы. Каждая команда в каждом файле по-прежнему выполняется в CI на тестовом сайте. Набор содержит 2008 тестов, и шлюз команд документации теперь самая большая отдельная группа.ИзмененоРаботаетПроверяем собственные ограничения протокола sitemap (#124):
SITEMAP_TOO_MANY_URLSприболее чем 50 000 записей в одном файле,
SITEMAP_TOO_LARGEпри более чем 50 МБ без сжатия иSITEMAP_URL_DUPLICATEDдля URL, объявленного в нескольких sitemap, с названием обоих документов. Файл, превышающий любой из лимитов, недействителен, а не просто велик. Поисковая система может прочитать часть и отбросить остальное, и владелец сайта этого не увидит. Пороги берутся из протокола, а не из конфигурации. Оба парсера теперь записывают размер каждого документа в байтах и заявленное число записей. Находки называют дочерний sitemap, а не индекс. Реестр вырос с 118 до 121 проверки.ДобавленоРаботаетДобавлен
docs/GUIDELINE.md, документ, который человек читает первым (#121): что это ичем не является, первый запуск от начала до конца…
Добавлен
docs/GUIDELINE.md, документ, который человек читает первым (#121). В нём: что это и чем не является, первый запуск от начала до конца, как выбрать скорость сканирования и понять, свои ли это ошибки, как читатьaudit.json, не обманываясь им, что меняет файл конфигурации и что он только стоит, шесть ошибок, которые все совершают первыми, что делать, если инструмент ошибается, и на что он вообще не может ответить. Ссылка на документ стоит первой в README, перед справочником.ДобавленоРаботаетДобавлен
docs/COVERAGE_SF_ISSUES.md, генерируется изseohead/sf/core/sf_issue_map.py.Он содержит все 320 проблем опубликованного каталога этой области. У каждой ровно один статус: найдена именованной проверкой, найдена именованной командой, найдена частично с указанием недостающей части, именованный пробел или решение с причиной (#119). Из 212 проблем в охвате 126 находятся сегодня, 17 частично. 41 — пробелы, 28 требуют того, что намеренно не построено. Доступность (92) и AMP (16) отклонены как отдельные решения, и их полные списки показаны, чтобы решение можно было проверить. Тест проверяет, что каждый упомянутый ID проверки и каждая команда всё ещё существуют, поэтому переименование ломает сборку, а не документ. Документ заменяет
docs/CHECKLIST_AUDIT.md, написанный без каталога под рукой.ИзмененоРаботаетЗагрузчик sitemap запрашивает адрес, который опубликовал sitemap, а не его
нормализованную форму (#115).
sitemap.crawl()возвращал только нормализованныйloc. Поэтому sitemap, объявляющий/a/, приводил к запросу/a. В большинстве CMS это 301, которое краулер сам выдумывал и затем сообщал как факт о сайте, а там, где форма без слеша не маршрутизируется, это 404. Теперь каждая запись хранитlocкак опубликованный, вместе сloc_normalizedдля потребителей, которые сравнивают по нему. Статистика редиректов из прежних сканирований, стартовавших с sitemap, по этой причине вызывает сомнения.ИзмененоРаботаетСтруктура скилла оператора перестроена в каталог контроллера (#111).
В
.claude/skills/теперь два уровня. 21 скилл метода, каждый из которых делает одну вещь хорошо, иcontrol/, который решает, какие из них запускать на сайте, на котором ещё никто не смотрел. Контроллер направляет, а не пересказывает. В нём пять подгружаемых подскиллов (охват, скорость и нагрузка, чтение аудита, проверка, результаты) и архив справочника из трёх файлов: дефекты, найденные на живых сайтах и то, что их выдало, какая совокупность описывает каждая проверка, и на что инструментарий вообще не может ответить. Шлюзы «только английский» и команд документации теперь покрывают каждый Markdown-файл в каталоге скилла, а не толькоSKILL.md.ДобавленоРаботаетДобавлен
tests/chains/: тестовый сайт, построенный из форм, которые реально ломаютцепочки: обе slash-формы одного URL, тело, которое не является валидным UTF-8, страница в windows-1251, шапка вне
<main>, ссылка на другой хост и путь, запрещённый robots. Он сканируется по loopback. Семнадцать проверок касаются запуска в целом, а не одного модуля (#112). Четыре свойства: сохранение (число не меняет смысла при передаче), популяция (находка относится к члену набора, который она описывает), детерминизм (два сканирования, два уровня параллелизма, один ответ) и представление (страница говорит, как её измерили). Правила популяции берутся из собственногоlogscan, поэтому противоречие, которое сканер может назвать, становится проверкой цепочки, которая его и утверждает.ИзмененоРаботает
reconcile_sitemapсообщает каждый URL так, как он был записан, а не так, как былнормализован.
Сравнение по-прежнему идёт по нормализованному ключу. Но находка, которая называла нормализованную форму, указывала на URL, которого нет нигде в сканировании. Читателю такая находка бесполезна, а анализатор аномалий не отличит её от находки о странице, которую не загружали.
ДобавленоРаботаетДобавлен
docs/scenarios/: десять сквозных цепочек, в каждой реальные команды попорядку, артефакт на выходе, стоимость и то, на что цепочка не отвечает (#110). Остальная документация перечисляет, что умеет инструментарий. Здесь описано, что он делает. Ссылка стоит в README над списком инструментов, поэтому агент, оценивающий репозиторий, находит цепочки раньше инвентаря. Каждая показанная команда выполняется на тестовом сайте в
tests/test_docs_commands_execute.py. Его экстрактор и шлюзы «только английский» и подсчёта теперь обходятdocs/на всех уровнях, а не только в верхнем.ДобавленоРаботаетДобавлены
log-scan(CLI) иseo_log_scan(MCP): читают собственные артефактызавершённого запуска и сообщают утверждения, которые не могут быть истинны одновременно (#109). Восемь правил, каждое написано по дефекту, который прошёл весь набор тестов. Среди них: записанный размер расходится с файлом на диске, доля текста больше 100%, проверка срабатывает чаще, чем есть страниц для срабатывания, находка о URL, который запуск не загружал, canonical назван редиректом, хотя этот URL отвечал 2xx в том же запуске, сводка расходится со своими строками, слова посчитаны на странице нулевого размера, и страницы измерены двумя способами, причём только часть из них сообщает, каким. Каждая аномалия называет оба значения и место, откуда каждое было прочитано. CLI выходит с кодом 2, если запуск противоречит сам себе, чтобы пайплайн остановился, а не публиковал числа.
ИзмененоРаботаетТест межпоточного пейсинга больше не измеряет настенные часы (#107).
_DispatchGateтеперь читает внедрённые часы сканирования, а неtime.monotonic()напрямую. Поэтому тест управляет им виртуальными часами, которые продвигаются только тогда, когда что-то засыпает. Моменты диспетчеризации — собственная арифметика краулера, а проверка точная. Прежняя форма сравнивала реальные интервалы с порогом 0,024 с и падала на неизменённом коде, когда машина была загружена.ИзмененоРаботаетЗакрыта вторая половина аудита ненаправленных настроек (#91).
http.headersподмешивается в каждый запрос рядом с заголовками учётных данных.speed.adaptiveуправляет задержкой и корректировкой параллелизма троттлера: счётчики таймаутов и ошибок сервера продолжают работать, потому что сдаться и отступить — разные механизмы.discovery.hyperlinks.storeи.crawl,discovery.external.storeиdiscovery.redirects.crawlтеперь определяют, что сканирование записывает и за чем следует.discovery.canonicals.*,discovery.external.crawlиdiscovery.redirects.storeудалены вместо подключения. Они называли возможности, которых у паука нет (следование canonical, обход чужих хостов), или утверждали то, что он не может удержать. Настройка, которая появляется в--config-helpи манифесте запуска и ничего не меняет, хуже отсутствующей. Список исключений канарейки покрытия теперь пуст: каждый путьDEFAULTSменяет наблюдаемый результат и назван тестом.ИзмененоРаботаетОпределять область контента по семантике самого документа, если ничего не настроено
(#96): сначала
main, затем[role="main"], затемarticle, и записывать, какой из них сработал, какauto_main/auto_role_main/auto_article. Прежнее значение по умолчанию — всё тело страницы без теговnavиfooter— на живом посте WordPress дало 126 слов шаблона из 433 (29%), включая ссылку «перейти к содержимому». Это завышение в одну сторону влияло наTHIN_CONTENTиLOW_TEXT_RATIOна каждой странице шаблона. Тегиheaderиasideдобавлены вDEFAULT_EXCLUDE_TAGSкnavиfooterдля резервного пути. Заданный селектор по-прежнему приоритетен; если он ничего не находит, используетсяfallback_default_body, а не молча выбирается другая область.ИзмененоРаботает
URL_NOT_IN_SITEMAPтеперь сравнивает страницы со страницами (#94).Раньше URL из sitemap сверялись с каждым адресатом в графе ссылок сканирования. На живом сайте из 124 страниц это сработало 392 раза: 362 файла изображений, на которые прямо ссылается галерея, пять внешних ссылок и 30 URL, которых сканер не запрашивал. Это составляло 74% отчёта и заглушало реальные находки. Теперь наблюдаемая сторона — это страницы, которые sitemap должен объявлять: загруженные, с кодом 2xx, HTML, того же хоста и индексируемые.
reconcile_sitemapполучает эту выборку отдельным аргументомcomparable, поэтомуSITEMAP_ORPHANпо-прежнему проверяет доступность по всем адресатам ссылок и не может придумать «сиротские» страницы. Отброшенное возвращается вlinked_not_comparable, а не теряется.ИсправленоРаботаетИсправить проверки канонических ссылок на сайте, который отдаёт обе формы URL — со слешем
и без (#95).
norm_urlнамеренно отбрасывает завершающий слеш, поэтому канонический адрес без слеша совпадает со страницей, у которой слеш есть. Но нормализованный индекс хранил одну страницу на ключ, а при сканировании типичного сайта WordPress их две:/x(301) и/x/(200). Если брать ту, что добавлена первой,CANONICAL_TO_REDIRECTсообщал о 78 живых страницах, чей канонический адрес отвечает 200. ТеперьAuditContextотдаётpages_by_normсо всеми страницами под ключом,page_by_normвозвращает вариант, который ответил 2xx, аCANONICAL_TO_REDIRECTиCANONICAL_NON_INDEXABLEсрабатывают, только если ни один вариант им не противоречит.ИсправленоРаботаетИсправить
size_bytes: теперь это тело ответа в том виде, как оно пришло по сети, додекодирования…
Исправить
size_bytes: теперь это тело ответа в том виде, как оно пришло по сети, измеренное до декодирования (#99). Раньше размер считался по декодированной строке, поэтому каждый байт, не являющийся корректным UTF-8, превращался в U+FFFD и при перекодировании занимал три байта: WebP-файл 739 КБ из реального сканирования записывался как 1,27 МБ, и коэффициент завышения был разным у каждого файла. Завышались изображения, PDF, шрифты и HTML в устаревшей кодировке (windows-1251), а вместе с ними и доля текста, вычисленная от этого знаменателя. HTTP-кэш хранит размер по сети вместе с записью, поэтому повторно выданная страница показывает то же, что показала живая загрузка. Схема переходит наhttp_cache.v2, а записи v1 перезагружаются один раз, а не отдаются без размера.ДобавленоРаботаетДобавить
docs/TOOL_REFERENCE.md, сгенерированный из определений инструментов MCP(
seohead/mcp/tool_reference.py,scripts/generate_tool_reference.py). Для каждого инструментаseo_*/sf_*в нём указаны аргументы с типом и значением по умолчанию, стоимость (сеть, записи, идемпотентность, платные запросы — читается из его профиляToolAnnotations) и заметки о поведении и режимах отказа из собственного docstring.tests/test_docs_drift.pyломает сборку, если документ расходится с определениями инструментов или не содержит какой-либо инструмент.ДобавленоРаботаетДобавить
tests/test_docs_commands_execute.py: извлекает каждую командуseohead ...,показанную в…
Добавить
tests/test_docs_commands_execute.py: извлекает каждую командуseohead ...из README, docs, skills и examples (scripts/doc_commands.py) и запускает её офлайн — против локального фикстурного сайта на loopback (tests/doc_fixtures/) и материализованных копийexamples/, проверяя чистый выход. Команды, которым нужна реальная инфраструктура (RDAP/DNS, лицензионный бинарник SF, платный ключ провайдера, серверmcp, который не возвращает управление), хотя бы разбираются живым парсером аргументов. Задокументированная команда, которая перестала работать, теперь роняет CI, а не уходит в релиз устаревшей.ИзмененоРаботаетПривести все 21 технический workflow-скилл (
.claude/skills/*/SKILL.md) к общей форме:Trigger, Anti-trigger, Preconditions (чек-листом), существующий Workflow, Decision points, Definition of done (чек-листом) и Cost. Исправлен устаревший счётчик покрытия команд внизу
docs/SKILLS.md: реальное число, пересчитанное сканированием каждого файла скилла, теперь фиксирует новый drift-тест.ИсправленоРаботаетИсправить счётчики инструментов и тестов, которые тихо разошлись с реальными реестрами…
Исправить несколько счётчиков инструментов и тестов, которые тихо разошлись с реальными реестрами: устаревшее число CLI-команд в
docs/USAGE.md,docs/COMPARISON.md,README.mdиdocs/TESTING.md, устаревшее число инструментов MCP вdocs/TOOLS.md, устаревшее число инструментов в справочнике вdocs/README.mdи число офлайн-тестов. Исправленные значения закреплены регрессионным тестом (test_stale_tool_counts_do_not_reappear).ДобавленоРаботаетДобавить четыре статических аудита Lighthouse, которым не нужны браузер и сторонний API
(#59):
MISSING_CHARSET,MISSING_DOCTYPE,VIEWPORT_MISSINGиNO_COMPRESSION. Каждый считается по данным, которые уже есть у сканирования.content_encoding,meta_charset,doctypeиviewportвошли в нормализованный словарь колонок, поэтому экспорт SF, где они попали как колонки Custom Extraction, питает те же проверки. Реестр вырос с 114 до 118 проверок.ИзмененоРаботаетПодключить десять оставшихся настроек сканера, которые проверялись и записывались в
манифест запуска…
Подключить десять оставшихся настроек сканера, которые проверялись, записывались в манифест запуска и описаны в
--config-help, но нигде не читались (#63).limits.max_response_bytes,speed.max_delay_seconds,robots.user_agent_tokenиspeed.stop_after_consecutive_timeoutsтеперь управляют поведением, которое раньше было зашито в код.robots.unavailable_means_stopопределяет, останавливает ли сканирование недоступный robots.txt или robots.txt с ответом 5xx, либо он считается без ограничений. Раньше недоступный robots.txt никогда не останавливал сканирование независимо от политики, а 5xx всегда останавливал; теперь оба случая — один и тот же «недоступен», и решает настройка.limits.max_url_length,limits.max_query_variants_per_path,http.retry_on_timeoutиdiscovery.follow_nofollow— поведение, реализованное заново.http.user_agentтеперь применяется к реальным запросам, а не подменяется стандартным User-Agent тулкита. Добавленыcrawl-describe-settings(CLI) иseo_crawl_describe_settings(MCP), чтобы агент мог изучить конфигурацию без доступа к файловой системе (#23).ДобавленоРаботаетДобавить пользовательский поиск (
tools/custom_search.py) и пользовательское извлечение(
tools/custom_extract.py) по уже собранному корпусу: фильтры наличия и отсутствия (исходный код, видимый текст, именованный CSS-элемент или узел XPath) и извлекатели CSS/XPath/regex. Оба сообщают, с каким представлением работали: со статической разметкой или с отрисованным DOM. Отсутствие учитывается честно: страница, загрузка которой не удалась, исключается и из числителя, и из знаменателя, а не считается отсутствующей. Извлечение запускает каждую пару (документ, извлекатель) под лимитом реального времени (SIGALRMна POSIX): патологическое выражение прерывает только свой документ, а прогон всё равно завершается.ДобавленоРаботаетДобавить классификацию позиции ссылок (
tools/link_position.py): навигация, шапка,боковая колонка, подвал или контент — по упорядоченному набору правил над цепочкой предков ссылки. Используется понятие контента из
content_area.py, а не вводится второе. Подключено к записи ссылок вcrawl/spider.pyза флагомlink_position.classify(по умолчанию выключено: позиция на каждую ссылку занимает память на большом сканировании). По всему сайту агрегируется функциейinlink_compositionизcrawl/linkgraph.py, которая теперь питает новую находкуINLINK_BOILERPLATE_ONLY— для страниц, на которые ведут ссылки только из шаблонного блока. Реестр вырос с 104 до 105 проверок.ДобавленоРаботаетДобавить восемь вычислений второго прохода после сканирования, доступных только по его
завершении…
Добавить восемь вычислений второго прохода после сканирования, которые становятся возможны только по его завершении (issue #15): внутренний показатель ссылок по графу рёбер
all_inlinks(LOW_LINK_SCORE); канонический адрес, на который не ведёт ни одна гиперссылка (UNLINKED_CANONICAL); обнаружение циклаrel="next"и серий без ссылок (PAGINATION_LOOP,UNLINKED_PAGINATION_SERIES); взаимность hreflang (HREFLANG_MISSING_RETURN_LINK); агрегаты состава входящих ссылок (ONLY_NOFOLLOW_INLINKS,ONLY_NONINDEXABLE_SOURCE_INLINKS); конкретный кратчайший путь обнаружения от стартовой точки сканирования (DEEP_DISCOVERY_PATH); собственный расчёт смешанного контента (INSECURE_SUBRESOURCE) и кластеризация почти-дублей по сохранённому тексту страниц (NEAR_DUPLICATE/DUPLICATE_BY_HASH), где впервые в аудит подключеныtools/duplicate.pyиtools/content_area.py.ORPHAN_PAGE,SITEMAP_ORPHANи две новые проверки «без ссылок» теперь не выдаются как находки: на сканировании, которое агрегатор пометил как частичное, они фиксируются как названный пропуск, потому что «на это никто не ссылается» нельзя доказать на обрезанном сканировании. Реестр вырос с 104 до 114 проверок.ИзмененоРаботаетСверить реестр сканирования с внешним чек-листом технического SEO и закрыть восемь
простых, проверенных пробелов: пять проверок hreflang (некорректные коды языка и региона, отсутствие самоссылки, отсутствие x-default, дубли записей, неканонические цели), две директивы robots (
notranslate,unavailable_after) и канонические URL с фрагментом. Реестр вырос с 96 до 104 проверок. См.docs/CHECKLIST_AUDIT.md.ДобавленоРаботаетДобавить
asset-weight-check: загружает CSS/JS, на которые ссылается страница, исообщает о блокирующих рендер ресурсах…
Добавить
asset-weight-check: загружает CSS/JS, на которые ссылается страница, и сообщает о ресурсах, блокирующих рендеринг, слишком больших файлах, дублирующихся библиотеках (по хешу содержимого), отсутствии минификации, отсутствииfont-display, устаревшем JS с полифиллами и отсутствии сжатия и долгого кэширования.ДобавленоРаботаетДобавить
crawl-site --sitemap <url>(иsitemaps.auto_discoverв--config):стартовые URL берутся из sitemap…
Добавить
crawl-site --sitemap <url>(иsitemaps.auto_discoverв--config): нативный сканер стартует с URL, объявленных в sitemap, переходит по ссылкам с каждого из них и сверяет объявленный и наблюдаемый наборы вsummary.sitemapфайлаaudit.json— под теми же идентификаторами проверокSITEMAP_ORPHAN/URL_NOT_IN_SITEMAP, которые уже выдаёт конвейер Screaming Frog.ДобавленоРаботаетДобавить
crawl-site --config-help, генерируемый изseohead/crawl/config.py, и скрытьфлаги…
Добавить
crawl-site --config-help, генерируемый изseohead/crawl/config.py, и скрыть--max-depthи--min-delayиз--help(по-прежнему принимаются), чтобы набор флагов перестал расти с каждой новой настройкой сканера.ИзмененоРаботаетРазделить определение технологий на шаг загрузки и чистый шаг
analyze_tech.Сохранять идентификаторы аналитики и менеджеров тегов, а не только их названия, и добавить отчёт
tag_coverage: он группирует наличие по шаблону URL и помечает, каким способом измерена каждая страница.ИзмененоРаботаетРазрешать цепочки и петли редиректов вторым проходом по собственным целям редиректов
завершённого сканирования. Теперь
REDIRECT_CHAIN/REDIRECT_LOOPне требуют нативного отчёта Redirect Chains из Screaming Frog: экспорт в облегчённом профиле или прогонcrawl-siteдают те же находки без дополнительных действий.ДобавленоРаботаетДобавить настраиваемую область контента (
content_area.py), которая ограничивает подсчётслов основной областью…
Добавить настраиваемую область контента (
content_area.py): она ограничивает подсчёт слов основной областью, по умолчанию исключая навигацию и подвал, и не влияет на поиск ссылок. Выбранная стратегия выводится для каждой страницы.ИзмененоРаботаетРазделить точные и почти-дубли в
duplicate.py: точные совпадения хешируются поизвлечённому тексту (а не по сырым байтам) и исключаются из кластеров почти-дублей; по умолчанию сравниваются только индексируемые страницы.
ДобавленоРаботаетДобавить отчёт о согласованности шаблонных блоков (
boilerplate_report.py), которыйхеширует…
Добавить отчёт о согласованности шаблонных блоков (
boilerplate_report.py): он хеширует шапку, навигацию и подвал каждой страницы и отмечает группы шаблонов, которые встречаются лишь у части страниц.ДобавленоРаботаетДобавить извлечение Markdown без внешних зависимостей (
markdown_extract.py): толькообласть контента…
Добавить извлечение Markdown без внешних зависимостей (
markdown_extract.py): рендеринг только области контента и рендеринг всего документа.ИзмененоРаботаетПодключить
markdown_extractиboilerplate_reportк CLI и MCP на уровне поверхности…Подключить
markdown_extractиboilerplate_reportк CLI и MCP какmarkdown-extract/seo_markdown_extractиboilerplate-report/seo_boilerplate_report(47 основных инструментов, было 45). Флагonly_indexable, который уduplicate_checkуже был на уровне обработчика, добавлен в сигнатуру MCPseo_duplicate_check, где его пропустили. Путь URL вcitability-checkпереведён с поляtextпарсера (весь документ одной свёрнутой строкой без абзацев и заголовков) на Markdown области контента изmarkdown_extract. Это устраняет и разбавление шаблоном, на которое указывала задача, и скрытую ошибку: плоский текст молча обнулял измерения Answer-Blocks и Structure-Quality для каждого живого URL. Намеренно не ограничено: само полеtextпарсера остаётся по всему документу, потому что извлечение schema-фактов вpage_facts.py(ссылкиsameAsна соцсети, breadcrumbs, регулярные выражения для цены и рейтинга) опирается на факты, которые законно живут в виджетах шапки и подвала, а область контента их исключает. Также не тронуты проверкиTHIN_CONTENT/LOW_TEXT_RATIOвsf/core/rules.py: ихword_count/text_ratioберутся из колонок экспорта самого Screaming Frog. Это данные стороннего инструмента, и без сырого HTML тулкит не может пересчитать их без повторной загрузки каждой страницы, что сломало бы офлайн-дизайн аудита SF без запросов. Собственный сканер тулкита (crawl-site) получает ограничение области контента бесплатно: подсчёт слов берётся прямо изparser.parse_html.ИзмененоРаботаетЗаписать соглашение об именовании (
docs/NAMING.md) и устранить коллизии базовых имёнмодулей и тестовые файлы, названные по процессам, которые оно выявило. Имена команд CLI, обработчиков и инструментов MCP не изменились.
- ДобавленоРаботаетДобавить файлы онбординга для сообщества, цитирования и агентов без ключа API.
ДобавленоРаботаетДобавить скилл рабочего процесса
analytics-console-reviewс запросом разрешения и трипрактических рецепта.
- ИзмененоРаботаетЗадокументировать поддержку текущей линейки безопасности
3.x. ИзмененоРаботаетТребовать TLS 1.2 или новее и привязывать прямые проверки сертификатов к заранее
проверенным публичным адресам.
ДобавленоРаботаетДобавить кэш HTTP-ответов для
crawl-site(seohead/crawl/cache.py, включаетсянастройкой…
Добавить кэш HTTP-ответов для
crawl-site(seohead/crawl/cache.py, включается черезcache.mode: по умолчаниюoff, поэтому побочных эффектов за значением по умолчанию не возникает). Реализована настоящая семантика свежести HTTP:max-age/Expires, перепроверка поETag/Last-Modified, варианты с учётомVary, соблюдениеno-store/no-cache. Есть режимreplayдля отладки — он отмечается в манифесте и никогда не включён по умолчанию — и флагinvalidateдля явного принудительного обновления. Каждая загруженная страница несётcache_status(hit/revalidated/miss); прогон несётcache_statsиcache_replayи в ответе обработчика, и в блокеrunфайлаaudit.json, поэтому отчёт, собранный частично из кэша, сообщает об этом. Попадание в кэш не стоит запроса и не тратит ни паузу троттлинга, ни слот диспетчера параллельных запросов: ожидание выполняется внутри самогоfetch_one, только когда действительно вот-вот произойдёт сетевой запрос.ДобавленоРаботаетДобавить повторное использование по журналу в
seohead/core/runlog.py(
SEOHEAD_REUSE_POLICY, предельный возраст…Добавить повторное использование по журналу в
seohead/core/runlog.py:SEOHEAD_REUSE_POLICYзадаёт предельный возраст в секундах для каждого инструмента; по умолчанию пусто, то есть ничего никогда не переиспользуется. Настроенный, ещё свежий и успешный прошлый ответ возвращается вместо повторного вызова инструмента и помечаетсяreused: trueсreused_from_ts— и в результате, и в новой записи журнала, которую всё равно пишет. Свежесть всегда отсчитывается от момента, когда значение было реально получено, и никогда не продлевается самим переиспользованием.
3.0.0
Первый публичный снимок30 августа 2026 г.10 записей · Первый публичный снимок10 изменено
30 августа 2026 г.
10 изменено- ИзмененоРаботаетОдин пакет Python с 42 общими инструментами CLI/MCP.
ИзмененоРаботаетПять дополнительных инструментов MCP для Screaming Frog и анализатор сканирования на 96
проверок.
- ИзмененоРаботаетРазведка домена, CDN, технологий, безопасности, зеркал, регионов, ботов и обратных ссылок.
- ИзмененоРаботаетВалидация Schema.org и генерация связанного графа.
- ИзмененоРаботаетОграниченная оценка сайта по sitemap и отчёты XLSX, DOCX, CSV, Markdown и JSON.
- ИзмененоРаботаетНеобязательные интеграции с Wordstat, Yandex SERP, Arsenkin, Metrika и DataForSEO.
- ИзмененоРаботаетДвадцать один технический workflow-скилл и семь упакованных SEO-плейбуков.
- ИзмененоРаботаетЛокальный MCP через stdio и поддержка Docker; без GUI, облачного API и телеметрии.
ИзмененоРаботаетПубличный README, опирающийся на факты, с воспроизводимыми синтетическими визуалами
аудита, задач, интерфейса и отчётов.
- ИзмененоРаботаетПубличная граница релиза без истории и явные уведомления о сторонних компонентах.
Дата = день, когда изменение попало в код (git-дата фрагмента changelog.d/). Номер = закрываемый issue. Заголовок = первое предложение, подробности по клику.