Журнал изменений

Что изменилось в SpiderHead, релиз за релизом. Каждая запись указывает тип изменения и работает ли оно уже сейчас.

Релизы на GitHub
В разработке

Unreleased

С 3.1.065 записей

22 октября 2026 г.

7 изменено2 исправлено
  • ИзмененоРаботаетA results difference between two scans can now be attributed.#1529

    The new read-only scan-config-diff (CLI seohead scan-config-diff --before a.sqlite --after b.sqlite, MCP seo_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 as http.headers compares as one leaf, exactly as the manifest records it.

    #1529 (задача на GitHub)
  • ИзмененоРаботаетA native crawl now measures its own reading level.#1516

    The new checks.readability module 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, version flesch-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.

    #1516 (задача на GitHub)
  • ИсправленоРаботаетCrawls on hosts that enforce https no longer spend a redirect hop on every http URL.#1484

    The new opt-in http.upgrade_to_https setting 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 carries transport_upgraded: true in its record (persisted as pages.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.

    #1484 (задача на GitHub)
  • ИзмененоРаботаетA crawl started deep can now stay in its own subtree.#1481

    The new scope.start_folder_only toggle admits only URLs at or below the start URL's path folder: a crawl started at /blog/post walks /blog/ and everything under it, and links pointing above the folder are counted as unfollowed evidence (excluded under outside_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 in crawl-describe-settings. With the toggle off nothing changes.

    #1481 (задача на GitHub)
  • ИсправленоРаботает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 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 new ROBOTS_BLOCKED_OUTLINK finding (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: under report_only the same targets are reported (they would have been blocked), and under ignore the 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.

    #1486 (задача на GitHub)
  • ИзмененоРаботает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 alt, so anchor-text review treated every image link as unnamed. The parser now records that alt as the link's anchor with an anchor_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 reports null there rather than a false text-derived answer.

    #1518 (задача на GitHub)
  • ИзмененоРаботает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 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 setting discovery.record_invalid_targets records 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 new INVALID_LINK_TARGET check turns the pages that have them into findings with the raw values as evidence. A missing href and a pure in-page #anchor are 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.

    #1530 (задача на GitHub)
  • ИзмененоРаботаетHEADING_SKIP now flags heading-order jumps in both directions, completing the#1545

    heading-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 axe.heading_order behaviour the check was modelled on. Evidence rows carry from/to levels and texts for both directions.

    #1545 (задача на GitHub)
  • ИзмененоРаботает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

    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 остаётся побайтно одинаковым для каждой команды.

    #1514 (задача на GitHub)
  • ИзмененоБетаОбработчики MCP вынесены в отдельный пакет handlers.#1514

    Серверные обработчики теперь лежат в seohead/mcp/handlers/ и разделены по доменам: проекты, трафик, логи, источники, контент, семантика, workflow, сохранённые сканы, доказательства и экспорт BI, окружение и каталог. Ссылки на документацию и пути к исходникам обновлены под новую структуру.

    #1514 (задача на GitHub)
  • ИзмененоБетаТаблица 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-страницам и постраничную таблицу узлов из ядерной команды scan-graph вместо заглушки. «Проблемы» показывают самые крупные группы проверок по счётчикам ядра; таблица URL показывает и сортирует колонку Inlinks и предупреждает, если скан не сохранил наблюдений по ссылкам. Колонка Issue count, которую невозможно измерить, больше не предлагается. Экспорт и отчёты запускают ядерную команду scan-export для страниц или находок в CSV, XLSX, JSON или XML в выбранную папку; наборы данных сравнения и задач, заглушка колонок и история экспорта, которые ядро не может обеспечить, удалены. Настройки, которые сохраняются, но ещё не применяются, теперь видимо отключены с причиной в подсказке. Диалог конфигурации сканирования один раз выводит параметры без проверенного редактора, в режиме «только чтение», а не смешивает их со списком редактора; поле «Why this scan» в «Новом скане» объясняет, почему оно пусто.

    #1347 (задача на GitHub)
  • ИзмененоРаботаетДесктоп: нерабочие разделы — раздел «Краулер» теперь запускает разовое сканирование без#1347

    проекта.

    Десктоп: нерабочие разделы. Раздел «Краулер» теперь запускает разовое сканирование без проекта. Поле адреса, переключатель Site / List / Sitemap, лимит URL, Start / Stop, вкладки проверок, поиск по адресам, счётчики обзора, панель деталей и экспорт CSV/XLSX подключены к ядерным командам crawl-site --scan-out и scan-url-query; строка состояния показывает скорость, просканировано и осталось по данным самого ядра. При открытии экрана ничего не запускается, а временный результат удаляется по Clear, при следующем сканировании и при выходе из приложения. Пункты быстрого сканирования в меню открывают этот раздел. Значок «Unavailable in this core version» в верхней панели убран. «Сравнение» больше не открывается с ошибкой после чтения проекта: пустое сравнение — нейтральная подсказка выбрать два скана, а состояние «недоступно» показывается только при реальном сбое.

    #1347 (задача на GitHub)

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, привязанный к проекту, за явной опцией --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.

    #1343 (задача на GitHub)
  • ИзмененоРаботаетИменованные профили сканирования можно просматривать как проверенный JSON, выбирать через#1299

    seo_crawl_site и назначать по умолчанию для проекта…

    Именованные профили сканирования можно просматривать как проверенный JSON, выбирать через seo_crawl_site и назначать проектам по умолчанию; переопределения сканирования проекта накладываются поверх. - Оценка прогресса сканирования считает время для текущего известного фронта и отделяет его от общей длительности; цели сканирования по умолчанию нормализуют параметры utm_* и fbclid. - Активные нативные сканы проектов принимают разовые запросы паузы и остановки по идентификатору запуска и контрольной точке через существующий путь восстановления SQLite. - Basic/Digest-аутентификация, привязанная к хосту, и опциональное согласование ответов zstd используют ссылки на переменные окружения, явное подтверждение, аутентификацию только по HTTPS и бюджеты запросов. Результаты сканирования включают ограниченные оценки нагрузки; неизвестный размер диска сохраняется как null.

    #1299 (задача на GitHub)
  • ДобавленоРаботаетДобавлена сводка операционного статуса проекта: прогресс активных коллекторов, полнота#1291

    последнего скана, состояние папок, открытые задачи основного проекта, последняя записанная активность агента и сохранённый размер папки сканов. Состояние соединения остаётся неизвестным без живого heartbeat.

    #1291 (задача на GitHub)
  • ДобавленоРаботаетДобавлен машиночитаемый контракт core-info с проверенными ревизией и временем сборки,#979

    поддерживаемыми инструментами CLI и MCP и точной совместимостью с десктопом по ревизии; добавлены команда doctor только для чтения и инструмент MCP для проверки локальных предпосылок. seohead --version выводит версию пакета. - Добавлены условные чтения project-observe и project-activity с учётом ревизий и непрозрачными токенами; добавлены проверки новых версий с явного согласия и загрузка wheel и source с проверкой контрольной суммы, прогрессом, отменой и без автоматической установки.

    #979 (задача на GitHub)
  • ДобавленоРаботаетДобавлены предварительные оценки платных стадий и история статусов по стадиям для#1298

    проектов семантического ядра. - Поддержаны предпросмотр импорта CSV/XLSX с сопоставлением колонок, экспорт по области, постраничное чтение кластеров, аудируемый выбор посадочных страниц и локальные инсайты на основе доказательств.

    #1298 (задача на GitHub)
  • ДобавленоРаботаетДобавлены ограниченные действия страницы и пресеты для отрендеренных сканирований с#1302

    включением на уровне проекта, сохранённые различия сырых и отрендеренных элементов…

    Добавлены ограниченные действия страницы и пресеты для отрендеренных сканирований с включением на уровне проекта; сохранены различия сырых и отрендеренных элементов и сетевые сбои браузера; добавлены находки переполнения на мобильных, размера текста и размера цели по захваченной вёрстке. Добавлены скриншот первого экрана и явные метаданные представления DOM.

    #1302 (задача на GitHub)
  • ДобавленоРаботаетДобавлены точные состояния checks_run, checks_skipped, checks_disabled и итоги#1296

    реестра в сохранённые доказательства сканов…

    Добавлены точные состояния checks_run, checks_skipped, checks_disabled и итог реестра в сохранённые доказательства сканов проекта. Выполненные и пропущенные счётчики остаются непересекающимися, а отсутствующее покрытие аудита помечается как недоступное. - Сохранённые сканы показывают ограниченные окна статического и отрендеренного HTML с идентификацией скана и документа, хешами сырого тела и декодированного текста, а также страницы находок по точному URL через общие обработчики CLI и MCP. Детали URL включают ограниченное окно исходного HTML; недоступные и неоднозначные доказательства остаются явными. Сравнение тел поддерживает пары статический/отрендеренный, а также пары между сканами. - Статус скана показывает состояние целостности, затронутый скан, доступность контрольных точек и обнуляемые счётчики повреждений. Переносимые архивы проекта могут не содержать тел HTML, опускать тела старше 30 или 90 дней или сохранять только новейшие N распознанных сканов, оставляя таблицы доказательств нетронутыми.

    #1296 (задача на GitHub)
  • ИзмененоРаботаетРасширены запросы 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. Добавлена офлайн-команда 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 остались явно недоступными, поэтому ответ фасетов частичный.

    #1295 (задача на GitHub)
  • ИзмененоРаботаетЧек-лист проекта 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, сохраняя корректный декоративный alt="". Буквально отсутствующие атрибуты alt остаются находками с именем ARIA; видимым декоративным изображениям всё равно нужны размеры. - Находки по изображениям сохраняют область source/target/status, причину, документ и ограниченные порядковые позиции. Отсутствующие тела сохраняют известные положительные факты о числе страниц, не выдумывая URL изображения или ответ ресурса. Ошибки ответа изображения и пороги байтов сохраняют статус и причину. - Выбор изображений определяет исходные страницы после переоткрытия. Доказательства ресурсов называют сохранённые строки загрузки и объявлений рядом с исходными документами. Идентичность нативного изображения включает исходную страницу и область, намеренно не допуская схлопывания между страницами, и мигрирует старые отпечатки нативных изображений. Старые находки без исходной страницы сохраняют прежнюю идентичность; повторяющиеся элементы сохраняют точные счётчики и ограниченные выборки мест. - Синтетический магазин сохраняет исходные дефекты и 15 контрольных образцов и добавляет случаи с информативным пустым alt и отсутствующим размером на существующих товарах, не меняя счётчики сканирования.

    #1303 (задача на GitHub)

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 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 общий для парсера и отдаваемых проекций.

    #1304 (задача на GitHub)
  • ИзмененоРаботаетСырые атрибуты 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 остаются пробелами, пока не выбран и не проверен реальный адаптер. Авторизация внешнего провайдера требует литерального булева true; строковые или числовые значения не разрешают вызов эмбеддинга.

    #1307 (задача на GitHub)
  • ИзмененоРаботаетСсылки входящих принимают идентификаторы целей (inbox:<uuid>), чтобы заметка могла#1314

    ссылаться на касающуюся её цель. - Пункты чек-листа, которые ни разу не запускались и являются ручными, получают состояние not_run вместо review; в review остаётся только попытка, ожидающая решения. - Модель чтения Issues (доказательства observe по находкам) показывает счётчики по проверкам (by_check) и next_offset после первых 20 находок; findings_page листает остальные.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетЗапланированные сканы проектов (#1322, ядро): schedule.json в каждой папке проекта#1322

    хранит независимое расписание сайта…

    Запланированные сканы проектов (#1322, ядро): 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 в своих правилах.

    #1322 (задача на GitHub)
  • ИзмененоРаботаетworkflow-start требует только принятой цели владельца: достаточно --goal-id или#1314

    context.goal_id…

    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. Отсутствующий запасной вариант фиксируется как неполный, но не прерывает сканирование.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетРабочие пространства конкурентов сохраняют URL в том виде, в каком он введён:#1314

    сканирование начинается с URL с www…

    Рабочие пространства конкурентов сохраняют URL в том виде, в каком он введён: сканирование конкурента начинается с его URL с www, а не с голого хоста, и сканирование URL конкурента больше не отмечает пункты чек-листа владельца; результат записывается только в собственном рабочем пространстве конкурента. Открытие проекта с повреждённым рабочим пространством конкурента помечает его недоступным вместо ошибки.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетПокрытие чек-листа проекта теперь привязывается к потоковым отчётам 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. Каждая строка — открытая задача: это план, ещё не выпущено.

Основы десктопа

закрыто 10 из 14

Сначала рабочий десктоп: блокеры, размер 800×600, мёртвые вкладки, честные состояния (волна 1 плана десктопа)

  • ДобавленоЗапланированоDesktop: проверка владельцем на реальном проекте (визуал, сканы, проблемы, экспорт,#1358

    инструменты)

    #1358 (задача на GitHub)
  • ИсправленоЗапланированоDesktop: мёртвые вкладки, неактивные действия и экраны-заглушки#1347 (задача на GitHub)
  • ДобавленоЗапланированоWindows: падают нативный краулинг, журнал проекта и сборка Desktop; Desktop плодит пустые#1345

    окна и непригоден на 4K

    #1345 (задача на GitHub)

Паритет десктопа

закрыто 19 из 34

UX десктопа на уровне привычных краулеров: вкладки, колонки под фильтр, детализация обзора, сохранение раскладки (эпик #1522)

  • ДобавленоЗапланированоВкладки деталей работают с выделением нескольких строк#1498 (задача на GitHub)
  • ДобавленоЗапланированоЕдиное состояние активности для всех окон и элементов управления#1496 (задача на GitHub)
  • ДобавленоЗапланированоРежимы приложения, перестраивающие весь интерфейс#1490 (задача на GitHub)
  • ДобавленоЗапланированоОтсоединяемые вкладки как плавающие окна#1489 (задача на GitHub)
  • ДобавленоЗапланированоНастраиваемые наборы вкладок с сохранением по режимам#1488 (задача на GitHub)
  • ДобавленоЗапланированоПомощник визуального извлечения с подсказками селекторов#1461 (задача на GitHub)
  • ДобавленоЗапланированоДиаграмма контентных кластеров по группам схожести#1460 (задача на GitHub)
  • ДобавленоЗапланированоОблака слов для анкоров и основного текста#1459 (задача на GitHub)
  • ДобавленоЗапланированоDesktop: core crawl workflow basics#1349 (задача на GitHub)

Движок краулинга

закрыто 9 из 51

Вежливость и политики robots, повторы, бюджеты, обнаружение URL, масштаб хранения, жизненный цикл скана (эпик #1520)

  • ДобавленоЗапланированоСтартовые URL краулинга из Google Sheets#1527 (задача на GitHub)
  • ДобавленоЗапланированоСобирать каноникал и пагинацию из HTTP-заголовка Link с указанием источника объявления#1517 (задача на GitHub)
  • ДобавленоЗапланированоУправление идущим краулингом: сужение области и добавление URL на лету#1485 (задача на GitHub)
  • ДобавленоЗапланированоОпциональный краулинг маршрутов с идентификатором фрагмента#1482 (задача на GitHub)
  • ДобавленоЗапланированоАвтоматический лимит параллельных отрисовываемых страниц по доступной памяти#1480 (задача на GitHub)
  • ДобавленоЗапланированоСбой рендеринга как отдельный исход URL#1479 (задача на 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)
  • ДобавленоЗапланированоТратить краулинг-бюджет сначала на малую глубину#1468 (задача на GitHub)
  • ДобавленоЗапланированоГлубина клика отражает кратчайший путь обнаружения#1467 (задача на GitHub)
  • ДобавленоЗапланированоСтруктурная нормализация URL перед дедупликацией при краулинге#1466 (задача на GitHub)
  • ДобавленоЗапланированоЗагружать robots.txt не более одного раза на origin при параллельной работе#1465 (задача на GitHub)
  • ДобавленоЗапланированоУчитывать Retry-After и сбавлять темп при ответах с троттлингом#1463 (задача на GitHub)
  • ДобавленоЗапланированоВеб-форма авторизации для краулинга с рендерингом#1447 (задача на GitHub)
  • ДобавленоЗапланированоОпциональные ограниченные повторы при ответах 5xx#1446 (задача на GitHub)
  • ДобавленоЗапланированоРасширенные краулинг-бюджеты: глубина папок, на поддомен, на уровень глубины, на шаблон#1445

    пути, максимум ссылок на страницу

    #1445 (задача на GitHub)
  • ДобавленоЗапланированоПараметры генерации sitemap: priority, changefreq, PDF, изображения с CDN, файлы по#1444

    сегментам

    #1444 (задача на GitHub)
  • ДобавленоЗапланированоМногоразовые пресеты экспорта#1443 (задача на GitHub)
  • ДобавленоЗапланированоДоверенные пользовательские CA-сертификаты для краулируемого трафика#1442 (задача на GitHub)
  • ДобавленоЗапланированоСчитать хосты CDN и зеркал внутренней областью#1441 (задача на GitHub)
  • ДобавленоЗапланированоДвижок переписывания URL для области краулинга#1440 (задача на GitHub)
  • ДобавленоЗапланированоСобственное переопределение robots.txt для краулинга#1439 (задача на GitHub)
  • ДобавленоЗапланированоНастраиваемая политика принятия cookie при краулинге#1438 (задача на GitHub)
  • ДобавленоЗапланированоЭкспорт офлайн-архива сайта#1437 (задача на 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)

Анализ и поля данных

закрыто 10 из 64

Читабельность, векторы и семантика, поля по каждому URL, покрытие проверок, сводки (эпик #1521)

  • ДобавленоЗапланированоОбъединение нескольких табличных экспортов в одну книгу#1528 (задача на GitHub)
  • ДобавленоЗапланированоНаходки по доступности с выбором уровня WCAG и таксономией серьёзности по влиянию#1526 (задача на GitHub)
  • ДобавленоЗапланированоЗаписывать атрибут SameSite для каждого наблюдаемого cookie#1519 (задача на GitHub)
  • ДобавленоЗапланированоМногодвижковое пользовательское извлечение со статусом валидации#1513 (задача на GitHub)
  • ДобавленоЗапланированоСводный блок по составу краулинга#1512 (задача на GitHub)
  • ДобавленоЗапланированоПравила пересчёта статистики аудита на лету#1511 (задача на GitHub)
  • ДобавленоЗапланированоБалл внутренних ссылок как опциональная метрика после краулинга#1510 (задача на GitHub)
  • ДобавленоЗапланированоЭкспорт таблицы аудита по видимому режиму сравнения#1509 (задача на GitHub)
  • ДобавленоЗапланированоРазбивка аудита по сегментам с графиками серьёзности#1508 (задача на GitHub)
  • ДобавленоЗапланированоПанель рекомендаций по каждой находке с копированием и внешними ссылками#1507 (задача на GitHub)
  • ДобавленоЗапланированоДельта находок между двумя сканами с подсветкой улучшений#1506 (задача на GitHub)
  • ДобавленоЗапланированоДоля корпуса в процентах для каждой находки#1505 (задача на GitHub)
  • ДобавленоЗапланированоСортировка находок аудита по приоритету по умолчанию#1504 (задача на GitHub)
  • ДобавленоЗапланированоСчётчики сводки аудита с фильтром по типу#1503 (задача на GitHub)
  • ДобавленоЗапланированоДвухосевая таксономия серьёзности находок аудита#1502 (задача на GitHub)
  • ДобавленоЗапланированоОшибки JavaScript-консоли как находки уровня страницы#1487 (задача на GitHub)
  • ДобавленоЗапланированоПроверка ответов целей пагинации#1458 (задача на 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)
  • ДобавленоЗапланированоИзвлечение и аудит свойств и ссылок PDF-документов#1448 (задача на GitHub)
  • ДобавленоЗапланированоОценка углеродного следа страницы#1433 (задача на GitHub)
  • ДобавленоЗапланированоВекторный поиск по сохранённому корпусу#1432 (задача на GitHub)
  • ДобавленоЗапланированоАнализ частотности N-грамм по просканированному контенту#1431 (задача на GitHub)
  • ДобавленоЗапланированоСсылки и текст, видимые только после рендеринга, как полноценные находки#1429 (задача на GitHub)
  • ДобавленоЗапланированоДобавить проверки битых и закрытых в robots.txt внешних JS- и CSS-файлов#1427 (задача на GitHub)
  • ДобавленоЗапланированоДобавить проверку слишком большого числа JS- и CSS-файлов на странице#1426 (задача на GitHub)
  • ДобавленоЗапланированоДобавить проверку несоответствия языка в hreflang и html lang#1425 (задача на GitHub)
  • ДобавленоЗапланированоДобавить проверку некорректных значений href#1424 (задача на GitHub)
  • ДобавленоЗапланированоДобавить в сканы находки по вариантам главной с www и по http#1423 (задача на GitHub)
  • ДобавленоЗапланированоДобавить в сканы находки о наличии и формате llms.txt#1422 (задача на GitHub)
  • ДобавленоЗапланированоСообщать о невалидном sitemap.xml как о находке скана#1420 (задача на GitHub)
  • ДобавленоЗапланированоСообщать о невалидном robots.txt как о находке скана#1419 (задача на 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)

Проекты и сценарии

закрыто 8 из 10

Сценарии владельца сайта: задачи, выгрузки, отчёты по расписанию и их доставка (эпик #1314)

  • ДобавленоЗапланированоДоставка отчётов запланированного мониторинга по email#1531 (задача на GitHub)

Ребрендинг

закрыто 0 из 1

Переименование seohead → spiderhead: CLI, пакет, окружение, документация (#1523)

  • ДобавленоЗапланированоПереименовать CLI-бинарник, пакет и префикс переменных окружения с seohead на spiderhead#1523 (задача на GitHub)

Интерфейсы CLI и MCP

закрыто 7 из 12

Понятные ошибки, настоящая справка, ограниченный вывод при чтении, транспорты MCP (эпики #1410 #1421)

  • ДобавленоЗапланированоMCP-сервер как полноценный режим CLI с транспортами stdio и streamable HTTP#1525 (задача на GitHub)
  • ИсправленоЗапланированоПоказывать реальную подсправку для 'seohead sf' вместо заглушки с передачей аргументов#1406 (задача на GitHub)

ИИ-слой

закрыто 0 из 1

Цели промптов для каждого SEO-элемента поверх seo_ai_column, без привязки к провайдеру (#1524)

  • ДобавленоЗапланированоИИ-анализ страниц с настраиваемыми целями промптов по данным краулинга#1524 (задача на GitHub)

Качество кода

закрыто 0 из 2

Разделение «божественных» файлов на модули и направление зависимостей (#1514 #1515)

  • ДобавленоЗапланированоНаправление зависимостей: убрать инверсии импорта из ядра в функциональные модули#1515 (задача на GitHub)
  • ДобавленоЗапланированоРазделить чрезмерно крупные модули адаптеров и движков на связные части#1514 (задача на GitHub)

Distribution: installers & one-command install

закрыто 0 из 2

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

    расписание: дни недели и/или числа месяца, временное окно в часовом поясе сайта, включение и выключение, конкурентов, режим сканирования 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 только при явном вызове.

    #1322 (задача на GitHub)
  • ИзмененоРаботаетUser-agent для сканирования (#1322): пресеты (spiderhead, googlebot,#1322

    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 в своих правилах.

    #1322 (задача на GitHub)
  • ИзмененоРаботаетСохранённое сканирование проекта теперь отмечает автоматические пункты чек-листа, которые#1314

    оно измерило.

    Каждый включённый пункт проверки получает один из трёх результатов: succeeded, если сохранённый аудит выполнил проверку, а скан служит доказательством; unavailable, если сканирование пропустило или отключило её, и причина сканирования сохраняется; или unmeasured, если аудит вообще не упоминает проверку. Неизмеренный пункт сохраняет прежнюю запись и называется по имени в checklist_evidence, поэтому никогда не засчитывается как 0. Сканирование, которое завершилось ошибкой или было прервано, помечает свои автоматические проверки как failed с причиной сбоя. Тот же путь записи теперь обслуживает поток prepare, который раньше вёл собственную копию цикла. Проект с непроинициализированным чек-листом пропускается с указанной причиной.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетРабочие пространства конкурентов сохраняют URL в том виде, в каком его ввели:#1314

    сканирование конкурента стартует с его www-URL, а не с голого хоста. Сканирование URL конкурента больше не отмечает пункты чек-листа владельца; результат записывается только в рабочее пространство конкурента. Открытие проекта с повреждённым рабочим пространством конкурента помечает этого конкурента как недоступного, а не приводит к ошибке.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетКандидатов в конкуренты можно добавлять, просматривать и удалять из CLI#1314

    (project-competitors-add, project-competitors-list, project-competitors-remove) и через соответствующие MCP-инструменты seo_project_competitors_*. Каждый кандидат сохраняет URL как введён, включая хост с www; варианты с www и без него считаются одним сайтом при проверке дублей. Конкурент с хостом www больше не ломает подготовку и не приводит к сбою project-observe.

    #1314 (задача на GitHub)
  • ИзмененоРаботает--max-urls теперь бюджет страниц сканирования: явный бюджет страниц заполняет#1314

    незаданные бюджеты запросов…

    --max-urls теперь задаёт бюджет страниц сканирования: явно заданный бюджет страниц заполняет незаданные бюджеты запросов и времени (3 запроса и 2 секунды на страницу), поэтому сканирования на 50–300 страниц проходят без approve_large_crawl. Бюджеты выше пороговых значений проекта по-прежнему отклоняются.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетНамеренная остановка по бюджету URL сохраняется как завершённый захват с finish_reason#1314

    stopped_by_budget и временем finished_at, а не как interrupted без времени завершения. Его URL в очереди остаются для продолжения.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетURL конкурентов сохраняют хост как введён (например, www. остаётся), а не хранятся без#1314

    него.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетDesktop добавляет сайты конкурентов из буфера обмена или по одному через ядро, задаёт#1314

    лимит URL на сайт…

    Desktop добавляет сайты конкурентов из буфера обмена или по одному через ядро, задаёт лимит URL на каждый сайт и запускает их сканирование параллельно. Сайт конкурента считается просканированным только после завершённого сохранённого скана.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетНативные сканирования измеряют HSTS, смешанный контент и структурированные данные по#1314

    собственным сохранённым доказательствам, поэтому отсутствующий или устаревший экспорт SF больше не сообщает, что их нет. duplicate-check помечает запуск с нулём сравниваемых пар как неизмеренный. Общесайтовые находки шаблона (одинаковый заголовок блока, низкая доля текста) объединены в одну находку с количеством страниц (#1314).

    #1314 (задача на GitHub)
  • ИзмененоРаботаетПринятие цели владельца добавляет только задачу чек-листа этой цели.#1314

    Весь встроенный каталог больше не сверяется с coverage.json: встроенные строки добавляются по требованию, когда до них дотрагиваются.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетЗанятый чек-лист называет живого держателя (например, работающее нативное сканирование и#1314

    его pid), а не считает блокировку остатком. Блокировка записывает pid своего писателя; блокировка без живого держателя по-прежнему отображается как остаток.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетЗапуск рабочего процесса, заблокированный упавшим, недоступным, пропущенным или#1314

    прерванным шагом, всё ещё можно возобновить, а более поздний ожидающий шаг может быть зафиксирован за шагом, не давшим успеха. Шаги по-прежнему фиксируются в зарегистрированном порядке, а прерванный запуск отказывается принимать дальнейшие шаги.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетОбзор, записанный агентом, больше не делает ручной пункт или результат полностью#1314

    подтверждённым владельцем.

    Пункт остаётся в ожидании подтверждения владельца или проверки не агентом.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетСсылки из входящих принимают id целей (inbox:<uuid>), поэтому заметка может ссылаться#1314

    на цель, которой она касается.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетРучные пункты чек-листа, которые ни разу не запускались, показывают состояние not_run,#1314

    а не review. В состоянии review остаётся только попытка, ожидающая решения.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетМодель чтения Issues (доказательства observe для находок) отдаёт счётчики по проверкам#1314

    (by_check) и next_offset после первых 20 находок. findings_page листает остальные.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетНативные проверки сканирования (#1314): размер изображения (IMG_OVER_KB) теперь#1314

    измеряется по собственным загрузкам изображений сканирования, а статус sitemap (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 (задача на GitHub)
  • ИзмененоРаботаетЖурнал проекта (#1314): каждое событие проекта теперь также записывается одним пунктом в#1314

    log.md…

    Журнал проекта (#1314): каждое событие проекта теперь также записывается одним пунктом в log.md, а ядро автоматически добавляет записи о завершённых сканированиях (scans), построенных отчётах проекта и попытках чек-листа (agent). Записи попадают в events.jsonl и читаются через project-event-page. Автоматические хуки никогда не валят сканирование, отчёт или шаг чек-листа, которые описывают. project-event-append и seo_project_event_append сохраняют интерфейс и получают строку в log.md.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетНативное сканирование теперь сохраняет заголовки безопасности, которые читают проверки#1314

    (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.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетworkflow-start требует только принятую цель владельца: --goal-id (или#1314

    context.goal_id)…

    workflow-start требует только принятую цель владельца: достаточно --goal-id (или context.goal_id). Зарегистрированный промпт по умолчанию — skill:workflow/full-audit-v1, а пункт чек-листа — тот, что принимает созданную цель (custom:goal-<entry>). Отказы называют команду владельца, которая устраняет недостающую связь. Опции описаны в seohead workflow-start --help.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетПопуляции чек-листа принимают частичные объекты: обязательны только kind и source, а…#1314

    Популяции чек-листа принимают частичные объекты: обязательны только kind и source, остальные ключи по умолчанию не заданы. Отклонённая популяция называет свои недостающие или неизвестные ключи.

    #1314 (задача на GitHub)
  • ИзмененоРаботаетНативные сканирования проектов переходят на /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 остаются пробелами, пока не выбран и не проверен реальный адаптер. Для внешнего провайдера разрешение требует литерального булева true: строки и числа, которые лишь считаются истинными, никогда не разрешают вызов эмбеддинга.

    #1307 (задача на GitHub)
  • ИзмененоРаботаетНативные сохранённые аудиты теперь группируют битые внутренние ссылки по наблюдаемой цели#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 scan.v1. Структурные находки AMP проверяют исходный doctype, head/body, кодировку UTF-8, viewport, скрипт среды выполнения и объявления шаблонного кода. Парные цели AMP без корневого маркера AMP выделяются отдельно. Полные правила валидатора AMP остаются недоступными до решения по лицензии.

    #1304 (задача на GitHub)
  • ИзмененоРаботаетНачало проверок доступности: язык документа, подписи полей формы, альтернативы#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 вместе с ошибками источника, позиции и синтаксиса по каждому блоку в scan-structured-blocks. Широкие деревья свойств ограничиваются, а их лимит показывается. Последний документ для запрошенного URL и представления читается без изменения его скана.

    #1304 (задача на GitHub)
  • ИзмененоРаботаетСохранять частичные и недоступные структурированные данные, не скрывая подтверждённых#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, в схеме MCP seo_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 и#1059

    regex по одному сохранённому HTML-документу без скана и сетевого запроса. Каждый результат несёт свои значения и reason для пустого исхода (no_match, empty_html или budget_exceeded), поэтому пустой ответ никогда не подаётся как чистый результат (#1059). Это только вызов ядра. CLI- или MCP-инструмент пока не зарегистрирован, а получение живого URL намеренно не включено.

    #1059 (задача на GitHub)
  • ИзмененоРаботаетПроверка последовательности пагинации (PAGINATION_SEQUENCE_ERROR) теперь оценивает#1057

    серии с шагом: когда один шаг покрывает большую часть шагов серии…

    Проверка последовательности пагинации (PAGINATION_SEQUENCE_ERROR) теперь оценивает серии с шагом: если один шаг покрывает большую часть шагов серии, сообщается о нарушении этого шага (?page=1,3,5,8 нарушается между 5 и 8). Нерегулярные схемы смещений и ненумерованные серии остаются неоценёнными и называются пропущенными.

    #1057 (задача на GitHub)
  • ДобавленоРаботаетНовая проверка сканирования INTERNAL_NOFOLLOW_OUTLINKS (notice): называет каждую#1052

    страницу-источник, которая содержит внутренние исходящие ссылки nofollow…

    Новая проверка сканирования INTERNAL_NOFOLLOW_OUTLINKS (notice): называет каждую страницу-источник, на которой есть внутренние исходящие ссылки с nofollow, указывает их количество и ограниченную выборку целевых адресов. Она закрывает пробел на уровне страниц для строки «Internal Nofollow Outlinks» из Screaming Frog, которая до этого была partial. Проверка работает на нативных сканированиях и пропускается по имени в запусках «только экспорт» и по списку URL.

    #1052 (задача на GitHub)
  • ИзмененоРаботаетПарсер читает <link rel="alternate"> с атрибутом media, но без hreflang (отдельный#1051

    мобильный URL)…

    Парсер записывает объявления <link rel="alternate"> с атрибутом media, но без hreflang (отдельный мобильный URL), в parse_html как mobile_alternates (#1051). Проверка «Mobile Alternate Link» из SF по-прежнему остаётся пробелом: проверка, которая сравнивает канонический URL мобильной версии, ещё не написана.

    #1051 (задача на GitHub)
  • ДобавленоРаботаетДобавлена проверка HREFLANG_UNLINKED_TARGET (warning): целевой адрес#1050

    hreflang-альтернативы, на который не ведёт ни одна обычная гиперссылка…

    Добавлена проверка HREFLANG_UNLINKED_TARGET (warning): сообщается о целевом адресе hreflang-альтернативы, на который не ведёт ни одна обычная гиперссылка в сканировании. Теперь покрыт отчёт Screaming Frog «Unlinked Hreflang URLs». Проверка читает экспорт All Hreflang и колонку Internal:All Inlinks так же, как UNLINKED_CANONICAL. Ссылка на саму страницу не учитывается, а при частичном сканировании результат не выводится. Реестр вырос с 182 до 183 проверок.

    #1050 (задача на GitHub)
  • ИзмененоРаботаетРазмер изображений на отрисованных маршрутах: render-check теперь фиксирует собственный#1049

    размер каждого изображения в пикселях относительно его отрисованного блока и коэффициента плотности пикселей устройства (image_sizing: данные о завышенных и увеличенных изображениях). Это только доказательства: идентификатора проверки в SF-analyzer пока нет, поэтому «Incorrectly Sized Images» переходит из статуса «пробел» в «частично» (#1049).

    #1049 (задача на GitHub)
  • ИзмененоРаботаетSemantically Similar: статус остаётся gap, а в примечании теперь назван блокер.#1041

    Команда и инструмент MCP для семантического сходства есть, но адаптер эмбеддингов не поставляется, а запуск SF пока не вызывает этот модуль (#1041).

    #1041 (задача на GitHub)
  • ДобавленоРаботаетДобавлена проверка INTERNAL_LINK_SPONSORED_UGC (notice): ссылка в пределах сайта с#1040

    rel="sponsored" или rel="ugc"…

    Добавлена проверка INTERNAL_LINK_SPONSORED_UGC (notice): ссылка в пределах того же сайта с rel="sponsored" или rel="ugc" выводится с полным набором значений rel. Для неё нужен link_attributes.capture, как и для других проверок по rel. Без него она помечается как не измеренная.

    #1040 (задача на GitHub)
  • ДобавленоРаботаетДобавлено ядро генерации XML-карты сайта из сохранённого сканирования: select_indexable#1039

    оставляет только…

    Добавлено ядро генерации XML-карты сайта из сохранённого сканирования. select_indexable оставляет только HTML-страницы со статусом 200, которые ссылаются каноническим тегом на себя, не закрыты noindex и не заблокированы в robots.txt, и указывает причину для каждого исключённого URL. render_sitemaps записывает <urlset> либо набор файлов плюс <sitemapindex> при разбиении по 50 000 URL или 52 428 800 байт на файл. Вывод в CLI и MCP — следующим шагом.

    #1039 (задача на GitHub)
  • ДобавленоРаботаетДобавлены cloudflare-traffic (CLI) и seo_cloudflare_traffic (MCP): источник только#1026

    для чтения на базе Cloudflare GraphQL Analytics для анализатора логов, когда серверных логов нет (#1026, #1009). Он возвращает боты × URL × коды статусов × статус кэша по дням в формате log-analyze и помечен source: cloudflare-aggregated, потому что это агрегированные данные граничной сети, а не сырые логи (IP-адресов клиентов нет, поэтому обратная DNS-проверка невозможна). Дни, которые упираются в лимит 10 000 строк на страницу, делятся на временные окна. Вызов учитывается в журнале расходов как бесплатный провайдер. Токен берётся из CLOUDFLARE_API_TOKEN или SEOHEAD_CLOUDFLARE_TOKEN_FILE и никогда не выводится.

    #1026 (задача на GitHub)
  • ИзмененоРаботаетВнутренний оценщик находок Search Console, пока не подключённый к отчётам:#1025

    seohead/checks/search_console_findings.py соединяет страницы сканирования с нормализованным документом GSC и оценивает GSC_ORPHAN, NO_SEARCH_DATA и NON_INDEXABLE_WITH_SEARCH_DATA. Проверка пропускается с указанием причины, если сканирование частичное, окно данных неполное, коллекция выборочная или обрезанная либо доказательства не переданы. Пропущенная проверка никогда не отмечается как пройденная.

    #1025 (задача на GitHub)
  • ИзмененоРаботаетcrawl-enrich выводит четыре находки веб-аналитики из офлайн-CSV с URL в качестве ключа…#1024

    crawl-enrich выводит четыре находки веб-аналитики из офлайн-CSV, где ключом служит URL: аналитические орфан-URL, индексируемые страницы без данных аналитики, неиндексируемые страницы с визитами и показатель отказов выше 70%. Нужные колонки выбираются параметрами --visits-column и --bounce-column. Отсутствующая колонка отклоняется с указанием имени, нечитаемые значения подсчитываются и никогда не считаются нулём, а аналитические орфан-URL не выводятся при частичном сканировании. Получение данных Метрики и GA4 по каждому URL в реальном времени пока не включено (#990, #984).

    #1024 (задача на GitHub)
  • ИзмененоРаботаетКарта покрытия проблем SF: четыре проблемы веб-аналитики (Orphan URLs, Bounce Rate…#1024

    Карта покрытия проблем SF теперь относит четыре проблемы веб-аналитики (Orphan URLs, Bounce Rate Above 70%, No GA Data, Non-Indexable with GA Data) к тем, которые находит crawl-enrich из офлайн-CSV, а не к вне зоны охвата. sf run пока их не выводит.

    #1024 (задача на GitHub)
  • ИзмененоРаботаетЯдро лабораторного покрытия для неиспользуемых CSS и JavaScript (#1023, срез 1): чистый#1023

    анализатор принимает данные page.coverage из Playwright и сообщает по каждому ресурсу число неиспользуемых символов. Если ресурс в основном не используется и при этом большой, выводится находка. Сбор покрытия с отрисованной страницы — следующий срез.

    #1023 (задача на GitHub)
  • ИзмененоРаботаетПроверки пар AMP (#1020): AMP_NON_200, AMP_MISSING_CANONICAL,#1020

    AMP_MISSING_RETURN_LINK, AMP_NON_INDEXABLE_CANONICAL и AMP_INDEXABLE читают AMP-цель, которую десктопная страница объявляет через <link rel="amphtml">. Оцениваются только AMP-страницы, которые сканирование захватило; незахваченная цель — пропуск с указанием причины. Нативное сканирование теперь записывает разрешённую цель в колонку AMP HTML. Остальные десять правил SF для AMP по-прежнему отклонены.

    #1020 (задача на GitHub)
  • ДобавленоРаботаетДобавлена HTML_OVER_2MB — абсолютный потолок 2 МБ для HTML-документа, отдельный от…#1019

    Добавлена проверка HTML_OVER_2MB: абсолютный потолок 2 МБ для HTML-документа, отдельный от относительного к медиане LARGE_HTML. Теперь «HTML Document Over 2MB» из Screaming Frog соответствует ей, а не правилу 200 КБ.

    #1019 (задача на GitHub)
  • ДобавленоРаботаетДобавлено уведомление URL_HAS_PARAMETERS в аудит сканирования: внутренняя#1018

    HTML-страница, URL которой содержит параметры…

    Добавлено уведомление URL_HAS_PARAMETERS в аудит сканирования: внутренняя HTML-страница, чей URL содержит параметры запроса, выводится независимо от канонического тега. URL_HAS_PARAMS сохраняет более узкий смысл — проверку страниц без канонического тега (#1018).

    #1018 (задача на GitHub)
  • ИзмененоРаботаетДирективы robots (#1017): устаревшие noodp и noydir в meta robots или X-Robots-Tag#1017

    теперь дают уведомления NOODP и NOYDIR в аудите SF; раньше они числились вне зоны охвата. none (noindex+nofollow) покрыт регрессионными тестами как для пути X-Robots-Tag, так и для meta.

    #1017 (задача на GitHub)
  • ДобавленоРаботаетНовая проверка сканирования JS_CONSOLE_ERRORS (SF «Pages with JavaScript Errors»):#1015

    страница, в консоли которой при отрисовке были зафиксированы ошибки. Данные читаются офлайн из сохранённых sidecar-файлов консоли нативного сканирования, без повторной отрисовки. Запись, которую нельзя прочитать, — это явный пропуск, а не чистая страница. Требуется rendering.artifacts.console_errors.

    #1015 (задача на GitHub)
  • ИзмененоРаботаетСканирования теперь сообщают четыре отсутствующих заголовка безопасности на HTML-страницу#1013

    из сохранённого финального…

    Сканирования теперь сообщают о четырёх отсутствующих заголовках безопасности для каждой HTML-страницы по сохранённому финальному ответу: MISSING_CSP, MISSING_X_CONTENT_TYPE_OPTIONS, MISSING_X_FRAME_OPTIONS (закрывается директивой CSP frame-ancestors) и MISSING_REFERRER_POLICY. Страницы, чьи сохранённые заголовки не удаётся разобрать, считаются неизмеренными, а не чистыми. Сканирование без сохранённого результата пропускает их с указанием причины.

    #1013 (задача на GitHub)
  • ДобавленоРаботаетДобавлен валидатор закрытых спецификаций действий на странице (click, scroll,#1011

    wait_for_selector, wait_ms) со статическим бюджетом времени для сканирований с отрисовкой. Он пока не подключён к отрисовке, поэтому поведение сканирования не меняется (#1011).

    #1011 (задача на GitHub)
  • ИзмененоРаботаетlog-analyze читает журналы доступа в формате gzip (ротированные access.log.N.gz и#1009

    переименованные архивы)…

    log-analyze читает журналы доступа в формате gzip напрямую (ротированные access.log.N.gz и переименованные архивы), определяя формат по содержимому, а не по расширению файла. Обрезанный или повреждённый архив выводится как ошибка без частичных подсчётов.

    #1009 (задача на GitHub)
  • ИзмененоРаботаетscan-url-query получает готовые пресеты представлений (--preset, например#1007

    status_4xx, title_missing, title_over_60, h1_missing, noindex_meta), которые объединяются логикой И с фильтрами пользователя. Параметр --export PATH вместе с --export-format csv|xlsx записывает все подходящие строки в новый файл. Экспорт отказывается работать сверх --export-max-rows (по умолчанию 100 000) и никогда не перезаписывает файл.

    #1007 (задача на GitHub)
  • ИзмененоРаботаетПравила допустимости rich result вынесены из исходного кода Python в#1001

    seohead/data/rich_results_rules.json — версионированный файл данных, поставляемый вместе с пакетом. Поле version этого файла проставляется как rules_version в каждом вердикте rich result, поэтому изменение правила означает изменение данных, а не кода.

    #1001 (задача на GitHub)
  • ИзмененоРаботаетВердикты rich result (check_schema и проверки по сохранённым структурированным данным)#1001

    теперь несут rules_version, поэтому каждый результат называет набор офлайн-правил, который его выдал.

    #1001 (задача на GitHub)
  • ИзмененоРаботаетДобавлено описание шести служебных и генераторных скриптов, на которые в документации не#997

    было ссылок…

    В 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).

    #997 (задача на GitHub)
  • ДобавленоРаботаетКонвейер семантического ядра добавлен как seohead/semantics со своей SQLite-базой на#995

    каждый проект: seohead semantics <stage> --project DIR (init, import, collect, clean, graph, exact, cluster, competitors, synonyms, report, excel, mine, sitematch, relevance, status, export), инструменты MCP seo_semantics_status, seo_semantics_run, seo_semantics_mine и seo_semantics_paid (платным стадиям нужен confirm_paid=true), кластеризация Louvain за новым дополнением semantics, упакованный скилл semantic-core и синтетический пример проекта. Платные вызовы провайдера в стадиях семантики помечаются в общем журнале расходов (#995).

    #995 (задача на GitHub)
  • ИзмененоРаботаетУдалён адаптер Telegram-бота с пошаговым режимом seohead/integrations/bot; квитанции#995

    доставки мониторинга теперь хранятся в seohead/projects/service_delivery.py (#995).

    #995 (задача на GitHub)
  • ИзмененоРаботаетscan-url-query возвращает click_depth — кратчайший путь по внутренним ссылкам от#992

    стартовой страницы сканирования — как колонку, фильтр и ключ сортировки. Страницы, до которых не доходит ни одна сохранённая ссылка, получают NULL (орфаны). crawl_depth не меняется и остаётся глубиной фронтира: для каждого URL, добавленного из sitemap, она равна 0. Если сканирование не сохраняло свои ссылки, запрос завершается с reason_code: click_depth_unavailable, а не выдаёт ложный NULL. Значение пересчитывается при каждом запросе по таблице links; сохранение его как индексированной колонки по завершении сканирования пока открыто, потому что требует решения о версии схемы (#992).

    #992 (задача на GitHub)
  • ИзмененоРаботаетscan-url-query и его инструмент MCP принимают необязательный аргумент facets (список#991

    групп или all)…

    scan-url-query и его инструмент MCP принимают необязательный аргумент facets (список идентификаторов групп или all) и за один проход по тем же фильтрам возвращают счётчики по группам: status_2xx–5xx, title_missing, canonical_missing, directives_noindex/nofollow, with_outlinks. Группы, которым нужна проекция (внутренние/внешние, sitemap, дубли и длина title, canonical на себя или на другой URL), пока не включены.

    #991 (задача на GitHub)
  • ИзмененоРаботаетПривязки источников проекта, первый срез (#990): project-sources-link,#990

    project-sources-unlink и project-sources-list (CLI, а также seo_project_sources_link|unlink|list через MCP) записывают, какие ID ресурсов провайдера использует проект, в файл sources.json рядом с project.json. Работает только офлайн: без обнаружения, без вызовов провайдера и без учётных данных; project.json никогда не переписывается.

    #990 (задача на GitHub)
  • ИзмененоРаботаетНативное сканирование: новая проверка IMG_BROKEN (#989, срез 1) сообщает о целях <img>,#989

    которые ответили 4xx/5xx, и указывает страницу-источник как доказательство. Она читает сохранённый граф ресурсов и честно пропускает проверку, если ни одно изображение не было измерено.

    #989 (задача на GitHub)
  • ДобавленоРаботаетДобавлен чистый классификатор soft-404 по сохранённому телу страницы#988

    (classify_stored_soft404): пустой текст, фраза об ошибке на тонкой странице и совпадение simhash с шаблоном 404. Он пока не подключён к сканированию и не выдаёт находок; это первый срез задачи #988.

    #988 (задача на GitHub)
  • ИзмененоРаботаетНативные сканирования проверяют цели canonical и hreflang, до которых не дошла ни одна#987

    ссылка, по одному разу на цель после сканирования (не более 5 000). Если цель отвечает 4xx/5xx или редиректом, выводятся CANONICAL_TARGET_ERROR, CANONICAL_TO_REDIRECT или HREFLANG_BROKEN_TARGET, как это уже происходило для просканированных целей (#987).

    #987 (задача на GitHub)
  • ИзмененоРаботаетНаходки по цепочкам редиректов и петлям из нативного сканирования теперь содержат полный#985

    путь переходов (details.path), поэтому при исправлении можно назвать каждый переход, который нужно заменить. См. #985.

    #985 (задача на GitHub)
  • ИзмененоРаботаетНаходки по цепочкам редиректов и петлям из нативного сканирования теперь также содержат#985

    details.inbound_links (внутренние ссылки, которые всё ещё ведут на первый URL цепочки, с анкорами, не более 20) и inbound_links_count. Если инвентаря all_inlinks нет, поле равно null и указана причина. См. #985.

    #985 (задача на GitHub)
  • ИзмененоРаботаетПроекты могут записывать ссылку на семантическое ядро как факты, введённые оператором#984

    (semcore_project, semcore_cluster_count, semcore_landing_mapping). Само ядро хранится в собственной базе и не сливается с базой проекта; обнаружение никогда не записывает эти факты, а переданный факт не может заявлять происхождение «обнаружение». Описано в docs/PROJECTS.md в разделе «Linking a semantic core» (частично, #984).

    #984 (задача на GitHub)
  • ИзмененоРаботаетDesktop: экран Link graph следует дизайну GraphFilters (холст и панель фильтров).#975

    Ядро пока не возвращает весь граф ссылок, поэтому холст показывает честное состояние ожидания, а фильтры остаются неактивными, пока этого не появится (#975).

    #975 (задача на GitHub)
  • ИзмененоРаботаетOAuth для GSC: provider-auth --action cancel (CLI) и seo_provider_auth#964

    action=cancel (MCP) отменяют ожидающую запись потока согласия в браузере; status показывает ожидающий поток, если он есть. Запись потока не хранит данных доступа и истекает через десять минут. Это первый срез #964: запуска и callback в браузере пока нет, поэтому публичная поверхность не создаёт потоков, а подключённый доступ по-прежнему не заявляется.

    #964 (задача на GitHub)
  • ИзмененоРаботаетcrawl-site --urls/--urls-file --project теперь регистрирует сканирование по списку URL#962

    как запуск наблюдателя (mode=list), поэтому он появляется в project-observe и project-scans вместе с артефактом в каталоге scans/ проекта. Сбойный сборщик записывается как failed; прогресс и возобновление запусков по списку пока не поддерживаются (#962).

    #962 (задача на GitHub)
  • ДобавленоРаботаетДобавлен структурированный план плейбуков: skill-list и scenario-list возвращают#955

    упорядоченные шаги каждого плейбука, а skill-show и scenario-show добавляют его заголовки и шаги, чтобы агент мог читать форму метода без разбора markdown (#955). Новая команда CLI scenario-list и инструмент MCP seo_scenario_list.

    #955 (задача на GitHub)
  • ИзмененоРаботаетscan-content-search принимает --kind regex (MCP kind="regex"), чтобы искать по#954

    сохранённым документам регулярным выражением Python. Некорректные выражения отклоняются до начала сканирования. Документ, который превысил бюджет времени для регулярного выражения, отмечается как недоступный, а не как отсутствующий.

    #954 (задача на GitHub)
  • ИзмененоРаботаетВызовы DataForSEO с потерянным ответом (сетевая ошибка после отправки запроса)#949

    записываются в журнал как…

    Вызовы DataForSEO, ответ на которые потерян (сетевая ошибка после отправки запроса), записываются в журнал с cost_unknown и charge_status: unknown, поэтому spend-report показывает их как неопределённые, а не засчитывает как измеренный вызов с нулевой стоимостью (#949).

    #949 (задача на GitHub)
  • ДобавленоРаботаетНовая команда scan-structured-blocks (CLI) и инструмент MCP#948

    seo_scan_structured_blocks: для одного сохранённого URL описывает каждый блок JSON-LD — строку источника, статус (valid / errors / warnings / parse_error), типы, плоский список свойств, ограниченный исходный JSON и ошибки графа Schema.org. Работает офлайн только по сохранённому полному телу страницы: без сетевых запросов и без изменений артефактов.

    #948 (задача на GitHub)
  • ИзмененоРаботаетcrawl-site без проекта, пишущий SQLite-артефакт сканирования, теперь делит потолок#942

    запросов на хост…

    crawl-site без проекта, который записывает SQLite-артефакт сканирования, теперь делит потолок запросов на хост с другими параллельными сканированиями того же хоста через приватное расписание в каталоге состояния пользователя (~/.config/seohead/.origin-pacing.sqlite). Раньше сканирования без проекта шли без регулирования темпа между процессами.

    #942 (задача на GitHub)
  • ИзмененоРаботаетПрофили crawl-site (#941): crawl-profile list печатает имена сохранённых профилей и…#941

    Профили crawl-site (#941): crawl-profile list выводит имена сохранённых профилей, а crawl-profile delete NAME удаляет один из них. Обе команды выводят JSON и отклоняют неизвестные имена, показывая список сохранённых профилей.

    #941 (задача на GitHub)
  • ИзмененоРаботаетПрофили crawl-site (#941): --save-profile NAME --config FILE сохраняет проверенную#941

    конфигурацию сканера как именованный профиль (отказ, если в ней есть заголовки с учётными данными); --profile NAME сканирует с ним, а --set по-прежнему применяется поверх. Профили хранятся в ~/.config/seohead/crawl-profiles или в каталоге, указанном в SEOHEAD_CRAWL_PROFILES. Просмотр и удаление профилей в этот срез не входят.

    #941 (задача на GitHub)
  • ИзмененоРаботаетcompare.v1 теперь перечисляет страницы, просканированные только с одной стороны#938

    (url_sets: only_in_before, only_in_after, счётчики). Если любое из сканирований частичное, url_sets.unproven равен true, поэтому отсутствие не подаётся как доказательство.

    #938 (задача на GitHub)
  • ИзмененоРаботаетПереходы в цепочках редиректов и canonical записывают статус, следующий Location#930

    (редиректы) и время ответа…

    Переходы в цепочках редиректов и canonical записывают статус каждого перехода, следующий Location (для редиректов) и время ответа, поэтому цепочку URL можно прочитать по сохранённым данным без повторного запроса (#930).

    #930 (задача на GitHub)
  • ИзмененоРаботаетПетли редиректов в цепочках по URL завершаются маркерным шагом ({"url": ..., "loop": true}#930

    ), который повторно не запрашивается, поэтому повторяющийся URL виден в сохранённых данных; final_url по-прежнему указывает на последний запрошенный переход (#930).

    #930 (задача на GitHub)
  • ДобавленоРаботаетШаги create и scan-ingest журнала remediation выводятся в CLI и MCP: remediation-create#926

    / seo_remediation_create создаёт один новый пустой журнал, привязанный к проекту (producer_build должен быть полным 40-символьным Git SHA; существующие пути отклоняются), а remediation-ingest / seo_remediation_ingest принимает один сохранённый аудит как baseline/history без повторного сканирования (повторный приём той же ревизии идемпотентен). Логика хранения не изменилась; это первый срез #926.

    #926 (задача на GitHub)
  • ИзмененоРаботаетcrawl_site и запуски сканирования сообщают effective_max_requests_per_second и#925

    warnings: предупреждение выводится, когда эффективная частота выше 2 req/s (порог строго больше 2). CLI печатает то же предупреждение в stderr; JSON в stdout и значения по умолчанию не меняются. Регулятор темпа (pacer) не изменялся.

    #925 (задача на GitHub)
  • ИзмененоРаботаетСтруктурированный журнал событий проекта (events.jsonl): добавляемые события с#923

    источником, автором и ограниченным текстом, которые читаются от новых к старым постранично с фильтрами по источнику и тексту. Доступно как project-event-append / project-event-page в CLI и как seo_project_event_append / seo_project_event_page через MCP (#923).

    #923 (задача на GitHub)
  • ДобавленоРаботаетДобавлены команда ai-column и инструмент MCP seo_ai_column, первый срез AI-столбца…

    Добавлены команда ai-column и инструмент MCP seo_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 и в справку CLI redirects-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

    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, вместо того чтобы сканировать большую таблицу.

    #931 (задача на GitHub)
  • ДобавленоРаботаетОбщее аудируемое состояние MCP с отзывом при запуске и на лету; безопасное присутствие#929

    клиентов в CLI…

    Добавлено общее аудируемое состояние MCP с отзывом при запуске и на лету для вызовов инструментов. Безопасное присутствие клиентов показывается через CLI.

    #929 (задача на GitHub)
  • ДобавленоРаботаетРегистрация клиентов с явного разрешения: предпросмотр, атомарная запись, проверенные…#929

    Добавлена регистрация клиентов с явного разрешения: предпросмотр, атомарная запись, проверенные резервные копии и восстановление без конфликтов.

    #929 (задача на GitHub)
  • ДобавленоРаботаетДобавлен scan-url-query (MCP seo_scan_url_query): только чтение, с серверной#927

    фильтрацией…

    Добавлен scan-url-query (MCP seo_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). Скан открывается с облегчённой проверкой идентичности и поколения схемы, а не полной валидацией, и никогда не изменяется.

    #927 (задача на GitHub)
  • ИзмененоРаботаетscan-link-inspect --view links (MCP seo_scan_link_inspect) постранично выводит ссылки…#924

    scan-link-inspect --view links (MCP seo_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). Существующие представления и поля не изменены.

    #924 (задача на GitHub)
  • ИзмененоРаботаетСтруктура пакетов переработана без совместимых заглушек: 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-сканирования сайта принимают max_urls=0 (собирать, пока очередь не исчерпана) и max_depth=-1 (отключить ограничение глубины). Бюджеты по времени и HTTP настраиваются отдельно, защита хранилища и прерывание с возобновлением продолжают работать. Устаревшие материализованные маршруты отказываются работать с неограниченным набором URL.

    #818 (задача на GitHub)
  • ИзмененоРаботаетСканирования только по 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. Точные границы и семантика сбоев — в docs/PDF_OVERVIEW.md.

    #818 (задача на GitHub)
  • ДобавленоРаботаетОперация провайдера GA4 page_views только для чтения: просмотры по дате, хосту и пути…#782

    Добавлена операция провайдера GA4 page_views только для чтения: количество просмотров по дате, имени хоста и посещённому пути, независимо от сессий по посадочным страницам. Используются существующие учётные данные GA4, транспорт и постраничный читатель отчётов с ограниченными повторами, исходами по квотам и правам доступа, явными метаданными часового пояса, семплирования и порогов, а также привязкой URL к заявленному origin. Сохранённые ограниченные доказательства провайдера нормализуются через существующее объединение и конвейер BI. Отсутствующий трафик остаётся недоступным, а не становится нулём.

    #782 (задача на GitHub)
  • ИсправленоРаботаетОбновления наблюдателя остаются ограниченными: покрытие по сайтам переиспользуется, живая#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 с объявленными#877

    origin и парами URL…

    Добавлены опциональные карты сравнения релизов url-correspondence.v1 с объявленными origin и парами URL, отказом при коллизиях, происхождением данных страниц и выводом release_review.v1.

    #877 (задача на GitHub)
  • ДобавленоРаботаетДобавить офлайн-проекцию когорт публикаций с подтверждёнными данными и происхождением дат…#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/)…

    Добавлена зафиксированная синтетическая фикстура рабочих листов (examples/reporting-pack/worksheets/): один CSV на каждый набор данных BI плюс манифест, детерминированно сгенерированные байт в байт из examples/audit.json и двух синтетических входов GSC/GA4. Она демонстрирует состояния: измеренный ноль, подавленные и отсутствующие данные, только внешние, без ключа, пропущенные проверки, недоступный набор данных и неполный квадрант. Воспроизводимость проверяется через scripts/generate_reporting_pack_worksheets.py --check.

    #836 (задача на GitHub)
  • ДобавленоРаботаетДобавить examples/reporting-pack/SETUP.md: механическое руководство владельца по#836

    импорту…

    Добавлен examples/reporting-pack/SETUP.md: механическое руководство для владельца по импорту шести листов в Google Sheets, подключению зарезервированных алиасов источников данных, построению пяти страниц блюпринта с объявленными элементами управления и вычисляемыми полями, включению разрешения на копирование и проверке свежей копии. Нативный шаблон Looker Studio остаётся внешним шагом, который разрешает владелец. ID отчёта, ссылка и запись в Google не включены.

    #836 (задача на GitHub)
  • ИзмененоРаботаетСохранять имена разделов, счётчики и контрольные суммы сгенерированного 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) и проверку аудита#827

    BROKEN_BOOKMARK…

    Добавлены 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 и в сводке аудита сохранённого сканирования. Ничего не загружается: оценка только для чтения и офлайн.

    #827 (задача на GitHub)
  • ИзмененоРаботаетПроверять нативные обратные ссылки hreflang по полным сохранённым объявлениям целевых#825

    URL, различая известное отсутствие обратной ссылки и цель, которая не просканирована или недоступна по телу. Сообщать о наблюдаемых альтернативах с noindex, сохранять исходные метки и нормализованные идентификаторы URL с контекстом дубликатов и конфликтов, помечать частичные связи совокупностей как не измеренные. Существующие поверхности аудита, CLI, MCP и отчётов передают те же находки без дополнительной загрузки.

    #825 (задача на GitHub)
  • ДобавленоРаботаетДобавить CANONICAL_TARGET_ERROR для загруженных канонических целей, которые отвечают#824

    4xx или 5xx…

    Добавлена CANONICAL_TARGET_ERROR для отчётов о загруженных канонических целях, которые отвечают 4xx или 5xx. Она содержит доказательства источника, цели, ответа и индексируемости. Неизвестные цели или цели с неполным статусом остаются недоступными. Известные варианты 2xx снимают вердикт об ошибке, а цели 3xx остаются под CANONICAL_TO_REDIRECT.

    #824 (задача на GitHub)
  • ДобавленоРаботаетДобавить CANONICAL_HOMEPAGE_GROUP для групп минимум из трёх загруженных индексируемых#824

    страниц…

    Добавлена CANONICAL_HOMEPAGE_GROUP для групп минимум из трёх загруженных индексируемых страниц в двух и более разделах пути с разными title и H1, которые каноникализируются на загруженную главную. Страницы self и home, страницы с query, распознаваемая пагинация, настроенные шаблоны пагинации и фильтров, неполные доказательства главной и частичные нативные сканирования не дают находок уровня сайта.

    #824 (задача на GitHub)
  • ДобавленоРаботаетДобавить объективные доказательства авторства, дат и страниц доверия в ограниченные#823

    аудиты (issue #823)…

    Добавлены объективные доказательства авторства, дат и страниц доверия в ограниченные аудиты (issue #823): восемь проверок уровня notice в 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-LD author/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.

    #823 (задача на GitHub)
  • ИзмененоРаботаетКлассифицировать 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 теперь хранит доказательства страниц, ссылок и форм в#817

    append-only JSONL sidecar-файлах…

    Legacy crawl-site --out-dir теперь хранит доказательства по страницам, ссылкам и формам в append-only JSONL sidecar-файлах во время сбора и возобновления, вместо удержания дублирующих списков в памяти. Контрольные точки проверяют счётчики sidecar-файлов. Более старые контрольные точки v4 с встроенными формами мигрируют без потери находок по формам. Существующий мост аудита называет свои границы материализации страниц, форм и ссылок и сохраняет собранные доказательства, когда аудит недоступен. Предыдущий отчёт сохраняется под устаревшим именем файла, а не выдаётся за текущий запуск. Нативная эскалация JavaScript читает записи страниц через перечитываемое представление SQLite, а не пересобирает все объекты страниц. Потоковая обработка больших аудитов полностью остаётся в #816/#817.

    #817 (задача на GitHub)
  • ИзмененоРаботаетХранить слишком большие нативные аудиты в упорядоченных 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

    манифест нормализованных входов для семантического сходства. Для каждого документа фиксируются хэш сохранённого тела, хэш точного декодированного входа, хэш нормализованного вывода, стратегия области контента и языковые признаки: собственный <html lang> страницы и доли буквенных скриптов. Сам нормализованный текст не сохраняется. --scan читает сохранённые полные тела офлайн по записанной конфигурации области контента, без повторного запроса. Отсутствующее или частичное тело остаётся явным пропуском, а не чистым пустым результатом (#801).

    #801 (задача на GitHub)
  • ИзмененоРаботаетПроверка 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#795

    seo_project_progress…

    Добавлены ограниченная постраничная команда CLI project progress и инструмент MCP seo_project_progress: счётчики состояний чек-листа и следующие действия. Представление использует результаты покрытия в заданной области. Процент выполнения аудита задач показывается только с явной пометкой и только если по каждому сайту в выборке согласован план и есть измеренный непустой знаменатель задач. Покрытие популяции URL остаётся отдельным показателем.

    #795 (задача на GitHub)
  • ИзмененоРаботаетЧек-листы проекта теперь фиксируют согласованную область аудита и честное покрытие…#794

    Чек-листы проекта теперь фиксируют согласованную область аудита и показывают честные коэффициенты покрытия (#794). project-checklist-init и seo_project_checklist_init принимают необязательный plan: рецензента, популяцию URL population, объявленную как complete_set, именованную sample или unknown, с её source, size или перечисленными urls, необязательные популяции по templates и необязательное соглашение по tasks (all_agreed или выборку selection из существующих ID пунктов чек-листа). План привязывается к идентичности сайта проекта и помечается номером ревизии записи. Запись плана переводит чек-лист на seohead.coverage.v3 и добавляет запись в сохраняемую историю планов. Повторная запись того же соглашения ничего не меняет. Изменённое соглашение помечает прежние доказательства устаревшими, а не пересчитывает их с новым знаменателем. Однопланные документы v3 мигрируют при чтении. Чтение, сверка и применение приоритетов никогда не повышают версию и не создают популяцию. Документы v1 и v2 продолжают загружаться без изменений. Пункты вне выборки отображаются как not_agreed и не входят ни в один знаменатель.

    #794 (задача на GitHub)
  • ИзмененоРаботаетЗавершение чек-листа теперь следует измеренной области: автоматический пункт с частичным#794

    сканом не засчитывается…

    Завершение чек-листа теперь следует измеренной области. Автоматический пункт, привязанный к сайту и опирающийся на ограниченное (частичное сканирование) измерение, остаётся незавершённым и не считается выполненным. Пункт, привязанный к явным образцовым URL, завершается, когда артефакт покрывает ровно эту область. Верхний флаг complete теперь означает, что аудит в заданной области завершён: все применимые согласованные задачи выполнены, нет ожидающих исключений, а согласованная популяция URL полностью покрыта проверенными измерениями. Поэтому неизвестная или неизмеренная область никогда не даёт статус завершённого аудита.

    #794 (задача на GitHub)
  • ИзмененоРаботаетСтатус чек-листа теперь возвращает coverage: пять отдельных коэффициентов —#794

    audit_tasks, checks…

    Статус чек-листа возвращает 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, если сайт не может обосновать свой знаменатель.

    #794 (задача на GitHub)
  • ИзмененоРаботаетЗапись not_applicable теперь проверенное исключение: нужны причина, рецензент…#794

    Запись not_applicable теперь проверенное исключение. Для неё нужны причина, рецензент и проверяемое основание: привязанный к проекту дайджест artifact или явная ссылка evidence. Проверенные исключения сохраняют стабильный ID и историю, выходят из знаменателей задач только по зафиксированному решению и отдельно перечисляются в exclusions. Отключённый пункт, устаревшая запись исключения или старая запись not_applicable, созданная до правила об основании доказательства, остаются в знаменателе как pending_exclusion, пока их снова не проверят. Поэтому отключение, удаление из каталога или переклассификация никогда молча не уменьшают согласованные счётчики. Свежее проверенное исключение для пункта, удалённого из каталога, закрывается штатно и не застревает в ожидании навсегда.

    #794 (задача на GitHub)
  • ДобавленоРаботаетАдресуемый промпт workflow/full-audit-v1 и сценарий full-audit через маршруты#793

    каталога CLI и MCP…

    Добавлены адресуемый промпт workflow/full-audit-v1 и сценарий full-audit через существующие маршруты каталога навыков и сценариев в CLI и MCP. Workflow использует уже поставляемые пути сбора и методики, а проверка и отчётность опираются на реальные доказательства. Подготовка проекта отделена от завершения полного аудита.

    #793 (задача на GitHub)
  • ИзмененоРаботаетПривязка решений по исправлению к неизменяемым артефактам проверки и точным хэшам#792

    доказательств до и после…

    Решения по исправлению привязываются к неизменяемым артефактам проверки и точным хэшам доказательств «до» и «после», включая потоковые базовые линии audit.v2.

    #792 (задача на GitHub)
  • ИзмененоРаботаетРезультаты исправлений с состояниями покрытия «представлено» и «полный охват»,#791

    знаменателями по задачам…

    Результаты исправлений выводятся с состояниями покрытия «представлено» и «полный охват», знаменателями по каждой задаче и ограниченными постраничными выборками кейсов для больших реестров.

    #791 (задача на GitHub)
  • ДобавленоРаботаетОграниченные повторные проверки исправлений по ключу реестра с защищённым верификатором…#790

    Добавлены ограниченные повторные проверки исправлений по ключу реестра. Они используют защищённый верификатор, потоково читают выборки audit.v2 и отказываются работать при смещении области.

    #790 (задача на GitHub)
  • ИзмененоРаботаетПроверка исправлений привязана к сохранённой идентичности аудита и исходной политике,#790

    влияющей на результаты. Повторно использованный UUID скана сам по себе больше не открывает старый кейс.

    #790 (задача на GitHub)
  • ДобавленоРаботаетДобавлен реестр исправлений ledger.v1 (seohead.storage.ledger, идентификатор#788

    приложения SEOL): отдельный SQLite-артефакт, привязанный к проекту. Он записывает находки, идентичность каждого вхождения, принадлежность затронутых URL и журнал наблюдений только на добавление из проверенных аудитов scan.v1 и scan.v2, не меняя исходные сканы. Источник привязывается по UUID скана, ревизии доказательств, хэшу аудита и идентичности производителя и конфигурации. Точные повторы не меняют состояние, конфликтующие байты при той же ревизии отклоняются атомарно. Покрытие capped и aggregate_only, а также данные unavailable сохраняются как данные и не считаются решёнными молча. Есть транзакционная миграция 0→1, полная проверка схемы и целостности при открытии и docs/LEDGER.md (#788).

    #788 (задача на GitHub)
  • ДобавленоРаботаетОдноразовый 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

    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 по периоду, границе часового пояса, идентичности, атрибуции, поисковой системе и детализации. Он также сообщает пригодность измеренных нулевых квадрантов для последующей когортной работы. Ограниченные источники держат строки и идентификаторы внутри приватного локального артефакта и возвращают только счётчики.

    #781 (задача на GitHub)
  • ДобавленоРаботаетОфлайн-опыт готовности провайдера: ссылки на учётные данные без секретов и явные#780

    состояния доступа…

    Добавлен офлайн-опыт готовности провайдера: ссылки на учётные данные без секретов, схемы маршрутов операций, метаданные квот и приватности и явные состояния доступа к цели. Сам факт наличия учётных данных не подтверждает разрешение.

    #780 (задача на GitHub)
  • ИзмененоРаботаетКоманда seohead watch расширена до наблюдателя проекта только для чтения с навигацией#775

    по находкам…

    Команда seohead watch расширена до наблюдателя проекта только для чтения: навигация по сохранённым находкам, подробности доказательств, состояние сохранённых представлений и проверки, а также явно ограниченные уведомления о входящих в MCP.

    #775 (задача на GitHub)
  • ДобавленоРаботаетДобавлена авторизованная синтетическая доставка отчётов с устойчивыми квитанциями#773

    идемпотентности…

    Добавлена авторизованная синтетическая доставка отчётов с долговечными квитанциями идемпотентности и безопасным при повторе поведением после перезапуска.

    #773 (задача на GitHub)
  • ИзмененоРаботаетНеподтверждённые заявки на доставку сохраняются после выхода процесса или некорректного#773

    подтверждения документа. Автоматическая повторная загрузка не происходит, если приём не удалось установить.

    #773 (задача на GitHub)
  • ИзмененоРаботаетПредпросмотр отчётов измеряется по сохранённым доказательствам: размер, дайджест#772

    источника…

    Предпросмотр отчётов измеряется по сохранённым доказательствам: отрисованный размер, дайджест источника, счётчики популяций, покрытие и профиль. Отсутствующие рендереры и слишком большие входы сообщаются до отправки. Бюджет JS мастера в режиме thorough приведён в соответствие с общим контрактом очереди.

    #772 (задача на GitHub)
  • ИзмененоРаботаетТочные подтверждённые идентичности отправки бота сохраняются при сбоях очереди и#771

    владения, доверенные обновления дедуплицируются, а статус, отмена, восстановление и доставка изолируются по инициирующему актору и чату. Одинаковые намеренные повторные запуски остаются отдельными заданиями.

    #771 (задача на GitHub)
  • ИсправленоРаботаетПосле перезапуска сервиса восстанавливается последнее подтверждённое задание актора и#771

    чата. Поведение отмены и повторного запуска после нового подтверждения сохраняется, а неподтверждённый черновик не возобновляется.

    #771 (задача на GitHub)
  • ДобавленоРаботаетПакет доказательств по обзору ПО для self-hosting, юридической и закупочной проверки#761

    (#761)

    Добавлен пакет доказательств по обзору ПО для self-hosting, юридической и закупочной проверки (#761). scripts/generate_review_pack.py создаёт и проверяет версионированный инвентарь зависимостей и лицензий: один профиль на каждую группу установки, с разрешёнными версиями и источниками лицензий, измеренными в окружении генерации. Требования, исключённые маркерами, не удовлетворённые спецификацией и не установленные, записываются, а не отбрасываются. Документ происхождения релиза связывает собранные дистрибутивы с тегом и ревизией исходников из встроенного манифеста сборки, а SHA256SUMS.txt покрывает всё перечисленное. Генерация отклоняет тег, который не совпадает с pyproject.toml. Проверка перепроверяет форматы и записанные хэши, заново распаковывает каждый дистрибутив, чтобы сверить его встроенный манифест, имя и версию из имени файла и поля Name и Version в собственном *.dist-info/METADATA или PKG-INFO с pyproject.toml, а не доверяет записи. Сканирование по маркеру SEOHEAD_REVIEW_CANARY_* подтверждает, что файлы пакета и диагностика не содержат подложенных учётных данных или маркеров клиентов. CI на каждом запуске пересоздаёт и проверяет пакет с одноразовым тегом, а релизный воркфлоу проверяет его и прикладывает к настоящему релизу v*.

    #761 (задача на GitHub)
  • ДобавленоРаботаетДобавлен docs/SOFTWARE_REVIEW.md: карта исходящих endpoint и потоков данных…#761

    Добавлен docs/SOFTWARE_REVIEW.md: карта исходящих endpoint'ов и потоков данных. Для каждой функции указано, к чему она обращается, что отправляет и является ли вызов необязательным. Документ описывает границу локального и удалённого режимов, хранение учётных данных и артефактов, статус телеметрии, безопасность и сопровождение, а также порядок проверки изменений релиза. Установка и развёртывание не дублируются: документ ссылается на runbook (#783, #787).

    #761 (задача на GitHub)
  • ДобавленоРаботаетОфлайн-проверка ёмкости и контрольных сумм 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 в report-build делятся по лимиту строк Excel, и создаётся хэшированный .xlsx.index.json с точными диапазонами записей, исходной популяцией, ссылками на выборку и покрытие. При перехваченной ошибке записи предыдущий отчёт сохраняется, а временные потоковые файлы очищаются при прерывании.

    #759 (задача на GitHub)
  • ИзмененоРаботает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…

    Добавлены verify-fixes / seo_verify_fixes для ограниченной повторной проверки выбранных URL: по сохранённым ID находок, представлению верификации или явному списку URL. Проверка использует записанную политику сканирования, пишет отдельный артефакт верификации и отчёт без перезаписи существующих файлов и различает статусы: исправлено, сохраняется, изменилось и не поддаётся проверке. Существующий аудит «после» можно проверить без сетевого доступа, только если у него есть отдельный UUID скана и более позднее записанное время наблюдения. Непроверенные данные и сигналы по всему сайту никогда не помечаются как исправленные.

    #755 (задача на GitHub)
  • ИзмененоРаботаетНативное сканирование URL может отбирать найденные маршруты по расширению конечного имени#749

    файла до запросов и по фактическому Content-Type ответа до разбора или хранения тела. Оба этапа фильтрации фиксируют свои решения и сохраняют данные о ссылках, статусах, заголовках и редиректах. Метаданные отфильтрованного HTML явно помечаются как неизмеренные. Скрипты и таблицы стилей выбираются независимо и имеют собственные бюджеты по размеру.

    #749 (задача на GitHub)
  • ИзмененоРаботаетЕсли тело HTML недоступно, находки на его основе теперь сохраняют явно пропущенное#749

    покрытие…

    Если тело HTML недоступно, находки, которые строятся на нём, теперь сохраняют явно пропущенное покрытие, а не принимают значения парсера по умолчанию за чистый результат или за наблюдаемое отсутствие метаданных.

    #749 (задача на GitHub)
  • ДобавленоРаботаетДобавлены проверяемые исключения по шаблонам URL для находок после анализа.#748

    Подавленные находки остаются в JSON аудита и в экспорте report-build вместе с сработавшим правилом и причиной. Итоги активных находок, оценка и список задач отражают заданную политику. Нативные артефакты сканирования сохраняют политику для офлайн-пересчёта; число правил и длина полей ограничены.

    #748 (задача на GitHub)
  • ДобавленоРаботаетДобавлен scan-export (seo_scan_export): офлайн-экспорт данных сканирования только для#747

    чтения…

    Добавлен scan-export (seo_scan_export): экспорт данных сканирования только для чтения, без сети, по версионированному контракту scan_export.v1. Он читает проверенный артефакт scan.v1 в SQLite или audit.json из SF Analyzer и пишет CSV (отдельный файл на каждый тип записей плюс манифест), XLSX (книга только для записи), потоковый JSON-конверт или XML по документированной схеме. Каждый результат содержит происхождение данных, число экспортированных строк, статистику запуска и явное покрытие: какие проверки выполнялись, были пропущены, отключены или остались неучтёнными. Ни один выбор полей это покрытие не убирает. --records и --fields дают проверяемую выборку по записям страниц, ссылок и находок; неизвестные типы записей или имена полей отклоняются до создания любого выходного файла. Отсутствующие значения остаются явными (JSON null, XML state="absent", CSV/XLSX \N), а не превращаются в выдуманные нули. XML формируется как сериализация с корректным экранированием UTF-8; внешний XML, DTD, таблицы стилей и сущности никогда не разбираются. Защита от внедрения формул в CSV/XLSX сохранена. XLSX отказывается от переполнения строк, столбцов и текста ячеек, а не обрезает их. Ошибка сериализации не оставляет правдоподобного частичного файла.

    #747 (задача на GitHub)
  • ИзмененоРаботаетВ crawl-site добавлена опциональная ограниченная проверка записанных внешних ссылок:#746

    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) отклоняется по имени, пока этот сборщик не получит такой этап.

    #746 (задача на GitHub)
  • ДобавленоРаботаетДобавлена явная проверяемая политика HTTP-прокси для нативного сканирования: страниц,#745

    sitemap, ресурсов и закреплённого браузера…

    Добавлена явная проверяемая политика HTTP forward-прокси для нативного сканирования: она действует на запросы страниц, sitemap, ресурсов и закреплённого браузера. Маршрут каждого запроса записывается с маскировкой чувствительных данных.

    #745 (задача на GitHub)
  • ИзмененоРаботаетЭтап рендеринга в нативном сканере теперь выбирает браузер через конфигурацию, а не#744

    жёстко зашитый Chromium. rendering.browser.engine выбирает chromium (по умолчанию), firefox или webkit через тот же защищённый путь Playwright. Неизвестное имя отклоняется при проверке настроек, а не при запуске. Если запрошенный движок не установлен, сканер выдаёт ошибку зависимости с решением (playwright install <engine>), а не тихо переходит на Chromium. Ограничение Firefox соблюдается честно: он отклоняет rendering.browser.mobile_emulation (is_mobile там не поддерживается), а независимый rendering.browser.touch_emulation (has_touch) по-прежнему передаётся в контекст. Пробы и полный рендер используют одну действующую конфигурацию, поэтому паттерн никогда не эскалируется браузером, отличным от того, который дал доказательства.

    #744 (задача на GitHub)
  • ИзмененоРаботаетrendering.browser.viewport_width и rendering.browser.viewport_height добавляют#744

    произвольные размеры вьюпорта рядом с существующими пресетами desktop и mobile. Пресеты по-прежнему определяют профиль так же, как раньше. Пара задаётся только целиком и ограничена диапазоном от 1 до 16384 px. Пользовательская пара заменяет только размеры пресета и не включает эмуляцию мобильного устройства или касаний: эти флаги оператор задаёт явно.

    #744 (задача на GitHub)
  • ИзмененоРаботаетrendering.browser.page_concurrency ограничивает число запросов браузера в полёте при#744

    эскалации…

    rendering.browser.page_concurrency ограничивает, сколько запросов браузера могут выполняться одновременно при эскалации, отдельно от speed.concurrency, который по-прежнему управляет вежливостью HTTP-сканирования. Значение по умолчанию 1 сохраняет последовательное поведение и вообще не создаёт пул. При значении больше 1 пробы и рендеры работают в ограниченном пуле воркеров, а все решения, фиксации и записи в SQLite остаются в потоке оркестратора в порядке отправки. Дедлайн рендера, бюджет URL и политики «выборочно» и «полностью» работают и при параллельности. Остановленная партия дожидается уже начатых страниц и не запускает новые. Прерванные или упавшие воркеры не оставляют после себя живых потоков, страниц, контекстов или браузеров.

    #744 (задача на GitHub)
  • ИзмененоРаботаетВыбранный движок, его фактически сообщённая версия, эффективный вьюпорт и заданная#744

    параллельность страниц…

    Выбранный движок, фактически сообщённая им версия, эффективный вьюпорт и заданная параллельность страниц записываются в манифест сканирования, в отпечаток и в данные о происхождении каждого отрендеренного документа, включая неудачные попытки: там фиксируется запрошенное, но успешный рендер не выдумывается. Оба пути эскалации учитывают настройки: каталоговое сканирование и нативное сканирование в SQLite. Кандидаты ссылок из рендера попадают в очередь через существующую дедупликацию, когда включён rendering.rendered_links.crawl.

    #744 (задача на GitHub)
  • ДобавленоРаботаетДобавлены опциональные проверки канонической политики для заданных шаблонов пагинации и#727

    фильтров в аудит по экспорту SF и нативному сканированию…

    Добавлены опциональные проверки канонической политики для заданных шаблонов URL пагинации и фильтров в конвейеры аудита по экспорту SF и нативного сканирования. Правила пагинации поддерживают цели «сама страница», «первая страница» или «посадочная страница»; правила фильтров — «сама страница» или «посадочная страница». Если политика не задана или цель отсутствует в данных сканирования, это остаётся неизмеренным. Проверки статусов ответа целевых страниц остаются отдельными.

    #727 (задача на GitHub)
  • ДобавленоРаботаетДобавлены возобновляемые архивы GSC Search Analytics в общем локальном SQLite-хранилище#718

    истории провайдеров…

    Возобновляемые архивы GSC Search Analytics добавлены в общее локальное SQLite-хранилище истории провайдеров и доступны единообразно через gsc-archive и seo_gsc_archive. Офлайн-статус, явная подготовка, ограниченный сбор и проверенные снимки используют одно ядро.

    #718 (задача на GitHub)
  • ИзмененоРаботаетСохраняются происхождение провайдера и движка и допускающие пустые значения метрики, в#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 с. Срез, который всё ещё отказывает, отправляется повторно с выборкой при 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 или доля не выше него) сохраняется и не повышается. Каждый отправленный запрос, включая отклонённый запрос на весь диапазон, попадает в журнал расходов.

    #714 (задача на GitHub)
  • ИзмененоРаботаетYandex Webmaster: операция indexing теперь читает реальный эндпоинт v4#713

    /indexing/samples вместо несуществующего /search-urls. Новая broken_links_samples читает /links/internal/broken/samples. Постраничная выборка соблюдает документированный лимит размера страницы для каждого эндпоинта (500 для запросов, 100 для списков примеров), а не отправляет limit=500 везде (#713).

    #713 (задача на GitHub)
  • ИзмененоРаботаетПостраничная выборка Yandex Webmaster теперь проверяет документированные count и форму#713

    списка…

    Постраничная выборка Yandex Webmaster теперь проверяет документированное поле count и форму списка каждой страницы, включая случай, когда count меньше числа возвращённых строк. На каждой странице запрашивается не больше оставшегося бюджета строк, поэтому обрезка по max_rows не может незаметно превратиться в ложный complete. Одиночная непостраничная выборка отдаёт returned/truncated как ограниченный срез. Статус partial ставится всякий раз, когда остаются непрочитанные строки. Некорректные страницы вызывают ошибку вместо ложного пустого полного результата (#713).

    #713 (задача на GitHub)
  • ИзмененоРаботает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

    Идентичность внешнего источника, покрытие по полям, повторные наблюдения и недоступные данные сохраняются в third_party_crawl.v1. Результат не считается нативным сканированием или аудитом SF.

    #819 (задача на GitHub)
  • ДобавленоРаботаетДобавлен опциональный транспорт удалённого браузера 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…

    Добавлен 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.

    #779 (задача на GitHub)
  • ИсправленоРаботаетИсправлен keywords-exact / seo_keywords_exact: он не мог вернуть результат, так как#720

    задача создавалась для несуществующего инструмента Arsenkin…

    Исправлен keywords-exact / seo_keywords_exact, который никогда не мог вернуть результат: задача создавалась для несуществующего инструмента Arsenkin с именем keywords_frequency, поэтому каждый вызов получал 404 WRONG_TOOL. Точный !W теперь уходит в инструмент wordstat с type=1, массив фраз передаётся в queries, а регион — одним элементом списка.

    #720 (задача на GitHub)
  • ИзмененоРаботаетДля !W запрашивается селектор overal: значения ws в Arsenkin — разные операторы…#720

    Запрашивается селектор overal для !W: значения ws в Arsenkin — разные операторы. base — широкий (WS), quoted — фраза в кавычках («WS»), overal — точная словоформа (!WS), которую запрашивает !W, а exact — строгий порядок ([!WS]).

    #720 (задача на GitHub)
  • ИзмененоРаботаетПеред отправкой удаляется пунктуация, которую провайдер отвергает: фраза с / или…#720

    Перед отправкой удаляется пунктуация, которую провайдер не принимает: одна фраза с / или кавычками отклоняла весь пакет с ошибкой 422 JSON_VALIDATION_ERROR. Переписанные фразы возвращаются в поле cleaned, чтобы было видно, какие из них измерены в другой форме.

    #720 (задача на GitHub)
  • ИзмененоРаботаетfrequencies возвращается как {phrase: {"base": N, "overal": N}} рядом с сырым ответом#720

    провайдера. Фраза, по которой результат содержит только другие регионы, опускается и перечисляется в warnings, а не получает чужие цифры.

    #720 (задача на GitHub)
  • ДобавленоРаботаетДобавлен ограниченный доступ к Topvisor только для чтения через общий CLI и обработчик#719

    MCP: учётные данные хранятся в центральных файлах, пагинация явная, операций с платными проверками нет.

    #719 (задача на GitHub)
  • ИзмененоРаботаетУстаревший блок sources.gsc в sources-doctor приведён в соответствие с#717

    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. Благодаря этому слишком большой, нечитаемый или некорректный файл отличается от настроенного, но непроверенного, и при этом его содержимое не раскрывается.

    #717 (задача на GitHub)
  • ИзмененоРаботаетАртефакты сканирования crawl-site теперь проставляют finished_at и finished, когда#712

    каждая принятая строка очереди достигла конечного состояния…

    Артефакты сканирования crawl-site теперь проставляют finished_at и статус жизненного цикла finished, когда каждая принятая строка очереди достигает конечного состояния, включая запуски с частично сохранёнными данными: crawl_partial уже перечисляет пропущенные наблюдения, поэтому опустевшая очередь больше не выглядит как прерванный сбор в scan-status, scan-list или истории (#712). Явно остановленный запуск (прерванный до принятия работы, отменённый или остановленный circuit breaker по ошибкам) сохраняет статус interrupted и записанную причину даже после опустошения очереди, в том числе через resume_or_finalize, поэтому пути остановки никогда не получают ложную отметку времени завершения.

    #712 (задача на GitHub)
  • ИзмененоРаботаетduplicate-check --scan и boilerplate-report --scan теперь потоково читают сохранённый#710

    корпус вместо падения на обычных сайтах…

    duplicate-check --scan и boilerplate-report --scan теперь потоково читают сохранённый корпус вместо падения на сайтах обычного размера: дедлайн открытия и проверки скана рассчитывается по размеру артефакта, а каждое чтение документа получает собственный дедлайн. Корпус на 1,5 тыс. страниц больше не заканчивается статусом interrupted. Бюджет входных байтов корпуса считает то, что анализатор действительно сохраняет: извлечённый Markdown для дубликатов и один дайджест на страницу для шаблонного текста, а не размер сырого HTML. Достижение границы корпуса даёт частичное покрытие с точными счётчиками prepared/eligible и указанием границы, которая остановила чтение (#710).

    #710 (задача на GitHub)
  • ИзмененоРаботаетMetrika report() и by_time() теперь локально отклоняют offset < 1 с ValueError,#707

    вместо того чтобы передавать его в Reporting API, который на offset=0 отвечает HTTP 400. Новые офлайн-тесты закрепляют нумерацию с единицы в metrika-report, seo_metrika_report и provider-collect aggregate_report, а также проверяют, что условия остановки постраничной выборки (total_rows, ROW_CAP) учитывают строки, пропущенные при нестандартном offset (#707).

    #707 (задача на GitHub)

2 октября 2026 г.

1 добавлено2 изменено
  • ИзмененоРаботаетmetrika-traffic-pdf на macOS: Chrome записывает PDF и продолжает работать; браузер#731

    теперь запускается без ожидания…

    metrika-traffic-pdf на macOS: Chrome записывает PDF и продолжает работать. Браузер теперь запускается без ожидания и останавливается после проверки PDF.

    #731 (задача на GitHub)
  • ИзмененоРаботаетYandex Webmaster: user_id определяется по токену; новые операции только для чтения…#713

    Yandex Webmaster: 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).

    #713 (задача на GitHub)
  • ДобавленоРаботаетНовый технический скилл traffic-report: клиентский месячный или годовой отчёт по

    Метрике, Webmaster и Search Console (конверсии, учтённые как визиты, проверки целей, товары, портрет покупателя, правила слайдов).

1 октября 2026 г.

1 добавлено1 изменено
  • ДобавленоРаботаетДобавлен metrika-traffic-pdf (seo_metrika_traffic_pdf): статический трафик-отчёт#731

    формата A4 в альбомной ориентации…

    Добавлен 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.

    #731 (задача на GitHub)
  • ИзмененоРаботаетОтчёты Метрики начинаются с offset=1: Reporting API нумерует с единицы, и каждый запрос…#707

    Отчёты Метрики начинаются с offset=1: Reporting API нумерует с единицы, а каждый запрос с offset=0 получал HTTP 400 (#707, #728, #729).

    #707 (задача на GitHub)

26 сентября 2026 г.

1 добавлено
  • ДобавленоРаботаетНативное сканирование добавляет HEADING_SKIP для скачков уровней H1–H6 в области#725

    основного контента…

    Нативное сканирование добавляет HEADING_SKIP для скачков уровней H1–H6 в указанной области контента. Заголовки шапки, подвала, навигации, боковой панели, а также явно скрытых или закрытых диалогов исключаются, чтобы элементы шаблона не создавали ложную иерархию. В запусках Screaming Frog только по экспорту проверка помечается как недоступная.

    #725 (задача на GitHub)

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 ищутся от корня сайта через robots.txt с запасным вариантом /sitemap.xml, а если все sitemap не раскрылись, это сообщается как ok: false.

    #703 (задача на GitHub)
  • ИзмененоРаботаетНативное сканирование можно возобновить после анонимных cookie, выставленных сервером, с#702

    фиксацией новой сессии…

    Нативное сканирование можно возобновить после анонимных cookie, выставленных сервером: новая сессия фиксируется без сохранения значений cookie. Сканирования с учётными данными и с постоянным профилем по-прежнему нельзя возобновить.

    #702 (задача на GitHub)
  • ИзмененоРаботаетСохранённые сканы задаются через --scan, встроенный JSON через --input; старые#701

    варианты…

    Сохранённые сканы задаются через --scan, встроенный JSON через --input. Устаревшие варианты --input для пути скана и --json-input работают ещё один релиз, но с предупреждением.

    #701 (задача на GitHub)
  • ДобавленоРаботаетДобавлено явное подтверждение, выключенное по умолчанию, для хранения ограниченных#700

    анонимных данных с заголовком Cache-Control: no-store. Тела с учётными данными по-прежнему не сохраняются.

    #700 (задача на GitHub)

9 сентября 2026 г.

10 добавлено9 изменено2 исправлено
  • ДобавленоРаботаетОфлайн-предпросмотр приоритетов проекта и версионированное применение политики по фактам#694

    стека…

    Добавлены офлайн-предпросмотры приоритетов проекта и явное версионированное применение политики на основе сохранённых фактов стека. Выбор оператора сохраняется, история политики ведётся атомарно, а объяснения приоритетов в читаемых отчётах соответствуют друг другу.

    #694 (задача на GitHub)
  • ИсправленоРаботаетУточнены рекомендации по рендерингу JavaScript, canonical, гигиене URL и notranslate#692

    без изменения проверок…

    Уточнены рекомендации по рендерингу JavaScript, canonical, гигиене URL и notranslate. Проверки в коде и уровни серьёзности не менялись.

    #692 (задача на GitHub)
  • ИсправленоРаботаетАдреса 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-режим crawl-site теперь по умолчанию пишет нативный SQLite-скан без конфликтов имён в каталог scans/ вызывающего. --out-dir остаётся явным устаревшим маршрутом для каталога, а список URL на входе и конфигурации кэша live/replay указывают этот маршрут, а не меняют режим сбора молча.

    #676 (задача на GitHub)
  • ИзмененоРаботаетЧистые сборки дистрибутива теперь встраивают проверенные данные о происхождении нативных#675

    SQLite-сканов, если исходный checkout недоступен.

    #675 (задача на GitHub)
  • ИзмененоРаботаетНеподтверждённые утверждения о фиксированном 301 (потере сигналов) и категоричном 302#671

    (без передачи веса) заменены в скилле аудита…

    Неподтверждённые утверждения о фиксированном 301 (потере сигналов) и категоричном 302 (отсутствии передачи веса) в скилле аудита заменены рекомендациями о постоянном или временном намерении и каноническом целевом URL со ссылкой на Google Search Central. Временные редиректы остаются корректными для временных изменений; сам код статуса не измеряет потерю позиций.

    #671 (задача на GitHub)
  • ИзмененоРаботаетrender-check --viewport mobile теперь использует один стабильный диагностический#670

    идентификатор смартфона для сырых и браузерных запросов. Явный --user-agent доступен через CLI и MCP, а каждое завершённое или частичное сравнение фиксирует действующий идентификатор и размер viewport.

    #670 (задача на GitHub)
  • ДобавленоРаботаетДобавлены read-only входы --scan для анализа дублей и шаблонного контента по корпусу, с#669

    покрытием сохранённых тел и происхождением…

    Добавлены read-only входы --scan для анализа дублей и шаблонного контента по корпусу: с покрытием сохранённых тел и указанием происхождения данных.

    #669 (задача на GitHub)
  • ДобавленоРаботаетДобавлен сгенерированный каталог входов команд, задокументировано решение по хранилищу#668

    сканирования, HTTP-кэша и журнала запусков.

    #668 (задача на GitHub)
  • ИзмененоРаботаетКлиентские отчёты в Markdown, CSV, XLSX, DOCX и задачи теперь используют понятные#660

    читателю названия находок и сохранённые доказательства воспроизведения вместо идентификаторов реестра и имён коллекторов. Исторические записи без достаточных доказательств прямо указывают на это ограничение, JSON-артефакты аудита не меняются.

    #660 (задача на GitHub)
  • ДобавленоРаботаетДобавлена project-facts: фиксирует факты о стеке проекта после создания, при#648

    необходимости по одному проходу tech-detect с соблюдением robots…

    Добавлена команда project-facts: фиксирует факты о стеке проекта после создания, при необходимости по одному проходу tech-detect с соблюдением robots.txt. Решения оператора приоритетнее обнаруженных данных. Если определение недоступно или неоднозначно, факт не записывается, а причина указывается.

    #648 (задача на GitHub)
  • ИзмененоРаботаетREADME начинается с контроллера проекта, Screaming Frog описан как перекрёстная вторая#648

    проверка, а не эталон паритета…

    README начинается с контроллера проекта, а Screaming Frog описан как перекрёстная вторая проверка, а не как эталон паритета.

    #648 (задача на GitHub)
  • ДобавленоРаботаетДобавлен examples/project-skeleton с инициализированным чек-листом без результатов,#648

    чтобы project…

    Добавлен examples/project-skeleton с инициализированным чек-листом без результатов: project status на нём показывает счётчики покрытия вместо not_initialized, а файл проверяется по актуальному каталогу.

    #648 (задача на GitHub)
  • ДобавленоРаботаетДобавлены контракты подготовки проекта, доказательств провайдеров, сохранённого корпуса,#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). Браузер возвращает обратно всё, что ему выставил собственный 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 по-прежнему никогда не сохраняется.

    #656 (задача на GitHub)
  • ИзмененоРаботаетТеперь названы счётчики отрендеренных страниц, которые флаг partial не может передать…#656

    rendered_bodies в результате crawl-site показывает, сколько отрендеренных DOM сохранено, и причину для каждого несохранённого. CLI печатает это рядом со строкой завершения, а не оставляет на флаге возможности, который говорит «partial» и при одном пропущенном DOM, и при всех. Запуск, который ничего не отбросил, ничего дополнительно не печатает. Счётчики читаются из артефакта сканирования, поэтому завершённое сканирование по-прежнему отвечает на тот же вопрос позже.

    #656 (задача на GitHub)
  • ИзмененоРаботаетСобираем og:url при нативном сканировании вместо того, чтобы помечать каждую страницу#654

    как лишённую его (#654).

    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 были двумя путями, которые расходились без теста, охватывающего оба.

    #654 (задача на GitHub)
  • ИсправленоРаботаетПерестаём читать cookie, который сайт выставил как учётные данные оператора, и явно#647

    сообщаем, когда запуск отбрасывает тела (#647). Сканирование использует один HTTP-клиент, а у клиента есть cookie jar: как только любой ответ нёс Set-Cookie, все последующие запросы уходили с Cookie:, а писатель корпуса классифицировал их как аутентифицированные. На публичном сайте с http.credential_headers = [] и credentials_acknowledged = false это отбросило 33 001 из 40 920 тел страниц, а запуск сообщал о страницах и ссылках так, будто сканирование полное. Всё, что вычисляется по сохранённому HTML этого сканирования (поиск почти-дублей, глубина и число узлов DOM, доля шаблонного контента, структура заголовков в теле, переанализ офлайн), тогда покрывало 7 903 страницы, а все процентные показатели по страницам в том же отчёте покрывали 40 920. Две совокупности были представлены как одна. Захват считается учётным, если запуск был настроен отправлять заголовок учётных данных для этого хоста. Это единственный способ, которым чувствительный заголовок может попасть в запрос, который строит сканер: http.headers отклоняется валидацией конфигурации. Сканирование с настроенными учётными данными по-прежнему исключает такие тела под credentialed, без изменений.

    #647 (задача на GitHub)
  • ИзмененоРаботаетНазваны счётчики, которые флаг partial не может передать…#647

    html_bodies в результате crawl-site показывает, сколько загруженных HTML-тел страниц сохранено, и причину для каждого несохранённого. CLI печатает это рядом со строкой завершения, а не оставляет на флаге возможности, который говорит «partial» и при одном пропущенном теле, и при четырёх пятых от всех. Запуск, который ничего не отбросил, ничего дополнительно не печатает. Списки заголовков запроса и ответа после редакции теперь сохраняют названия заголовков, которые редакция удалила, в поле x-seohead-redacted-headers, но никогда не их значения. Раньше два ответа, тела которых обрабатывались по-разному, записывали побайтово одинаковые списки заголовков, поэтому оператор, читающий артефакт, не мог понять, почему тело отсутствует.

    #647 (задача на GitHub)
  • ИзмененоРаботаетЗаписи changelog вынесены из CHANGELOG.md в отдельные файлы на каждое изменение под…#638

    Записи changelog вынесены из CHANGELOG.md в отдельный файл на каждое изменение в changelog.d/, поэтому pull request больше не конфликтует с каждым другим pull request, влитым раньше (#638). Каждая ветка добавляла запись в начало ## Unreleased, и эта одна строка становилась точкой конфликта: девять ручных разрешений на восемь pull request за две сессии, каждое с повторным пушем и новым CI-прогоном, и решение всякий раз было «оставить наш блок, потом их». Конфликт, ответ на который никогда не меняется, не несёт информации и лишь отвлекает от работы. Предложенное в issue исправление через .gitattributes, CHANGELOG.md merge=union, было измерено и отвергнуто ещё до этого. Union-слияние работает построчно: если обе записи содержат одинаковую строку (достаточно пустой строки внутри записи), оно оставляет одну копию и сообщает об успехе, молча удаляя строку другой записи без конфликта и без повода посмотреть. Первый тест с заведомо различными строками прошёл чисто и скрыл это. Обмен громкого конфликта на тихую потерю данных хуже самого конфликта, поэтому выпущено структурное решение.

    #638 (задача на GitHub)
  • ИзмененоРаботаетФрагмент называется по закрываемому issue (changelog.d/638.md), ключу, который по#638

    построению уникален для ветки…

    Фрагмент называется по закрываемому issue (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: шлюз, который держал бы его постоянно синхронизированным, снова поместил бы обе ветки в один файл и воссоздал бы конфликт, который это устраняет.

    #638 (задача на GitHub)
  • ИзмененоРаботаетОпасными были шлюзы документации, читавшие CHANGELOG.md, потому что шлюз, который тихо#638

    перестаёт что-либо проверять, хуже конфликтов…

    Опасными были шлюзы документации, читавшие 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.py changelog вообще не читают. Новый tests/test_changelog_fragments.py закрепляет каждый из этих ответов, а также именование фрагментов, детерминированный порядок, идемпотентную сборку и то, что две имитируемые параллельные ветки, каждая добавившая фрагмент, сливаются без конфликта.

    #638 (задача на GitHub)

Ранее (дата не указана)

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 для страницы, загруженной успешно. MCP seo_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" всегда присутствует как ключ в блоке source backlog: он задаётся при сборке из 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, то есть три строки без порядка и места. Теперь нативное сканирование записывает весь outline h1–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.json SF 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) во время платного вызова, то есть в post DataForSEO, /set Arsenkin и wordstat.topRequests, wordstat.dynamics, web.searchAsync в Yandex Cloud, раньше повторяло тот же payload без ключа идемпотентности и логировало только ту попытку, которая в итоге вернула ответ. Ни один из трёх провайдеров не даёт механизма идемпотентности для этих endpoint'ов, поэтому потерянный ответ больше не повторяется. Попытка записывается в журнал расходов (стоимость неизвестна, помечена attempt_failed: network_error), и вызов падает целиком, а не рискует вторым списанием. Идемпотентные чтения (/check и /get Arsenkin, опрос операций 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 уже был на уровне обработчика, добавлен в сигнатуру MCP seo_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. Заголовок = первое предложение, подробности по клику.