Files
obsidian-vault/work/projects/cpm-web-extension-public-attribution-2026-10-05.md

40 KiB
Executable File
Raw Permalink Blame History

updated
updated
2026-10-20

CPM Web Extension: attribution и сравнение релизов — 5 октября 2026

Исторический отчёт за 5 октября; контекст сверён 20 октября 2026. Таблицы, release-tag cutoffs и контрольные суммы сохранены без пересчёта. Актуальные PR/CI, отдельные когорты 12–14 октября и проверка обрезания history за 14 октября — cpm-status-2026-10-15. Новые числа нельзя переносить в прежние знаменатели.

#7376 заменяет раздельные события terminal episode report (daily+count), four-state stuck и initial;pre-stuck timeline с ...; PR закрыт без merge. Старый parser и параметры этой заметки не являются текущим wire contract. См. cpm-pr0-episode-telemetry-summary-2026-10-16. Совпадающие bg_events и ratios независимо deduplicated daily events не доказывают пару одного пользователя или recovery success.

Shared-pinned window-close fix #7473 merged 20 октября в release/macos/1.213.0 (9bcce0264e), default ON + remote failsafe; rollout/effect ещё не подтверждены (подробности — cpm-status-2026-10-15#P5 — merged 20 октября 2026); per-view Network recovery — #7459 с applied pixel, stable-origin P3 — #7493. Их наличие не превращает прежние snapshot cohorts в доказанные causal shares.

Историческое дополнение — 15 октября 2026

Исторический отчёт за 5 октября; контекст обновлён 15 октября. Таблицы, release-tag cutoffs и контрольные суммы этого дня сохранены без пересчёта. Текущие когорты 12–14 октября, PR/CI и P5/P6 tests — cpm-status-2026-10-15; переносить новые числа в прежние знаменатели нельзя.

Дополнительная проверка показала: фильтр сохранённых tabs перед явным didCloseTab уже присутствует в release 1.210, однако последующий didCloseWindow заставляет WebKit снова закрыть shared pinned tabs, которые возвращает delegate. Этот путь воспроизвёл P5/tab=false; наличие исходного M1 fix не доказывает устранение всего window-close контракта. Условный main-flag cycle воспроизводит P6, но его occurrence в этом или более позднем production-срезе не доказан. Полная область объяснения и контроли — основной статус §11–12.

Статус: первый завершённый UTC-день с данными версий iOS 7.240.0 и macOS 1.210.0. Главный сигнал — initialization.failed.after.*.daily; messaging.stuck.*.daily проверен отдельно как более поздний, менее точный сигнал. Выгрузка сделана 6 октября из Grafana ClickHouse metrics.pixels, интервал [2026-10-05 00:00, 2026-10-06 00:00) UTC, agent и appVersion зафиксированы. Основные таблицы ниже включают только события после публикации release tag каждой платформы; отдельный раздел сохраняет всё попавшее в выгрузку до публикации. Dashboard.

Вывод: после публикации macOS tag есть 77 первых init failures и 35 stuck с несовпадающим controller вкладки и отсутствующими extension scripts; до публикации таких строк нет. iOS session restoration по-прежнему даёт 952 первых сбоя, из них 604 со совпадающим controller, но без scripts и background view; у macOS после публикации таких session-restoration сбоев 68, из них 12 с той же сигнатурой. Крупнейшая группа с «исправным native-снимком» не доказывает нормальную загрузку или потерю initResp: health monitor измеряет отдельный вызов background → native refreshCpmDashboardState. После reload этот вызов вновь наблюдается гораздо чаще, но восстановление фактического initResp из пикселей не следует. Эффект исправлений tab lifecycle в совокупном тренде не выделяется.

1. Охват и контрольные суммы

После release tag: независимые имена .daily пикселей iOS 7.240 macOS 1.210
Первое initialization.failed.after.* 6 624 1 377
Позднее messaging.stuck.* 1 440 487
Первый неудачный post-reload CPM probe 670 232
CPM ответ после reload, оба recovery_from 963 = 916 stuck + 47 init 362 = 354 stuck + 8 init
CPM ответ без reload, initialization_failed 1 555 346
Сумма записей CPM daily по именам пикселей 11 252 2 804

Контроль после release tag: 6 624 + 1 377 = 8 001 первичных строк; 1 440 + 487 = 1 927 вторичных строк; 11 252 + 2 804 = 14 056 CPM daily записей по именам пикселей. До tag есть ещё 28 init, 2 stuck и 39 CPM daily записей, все на macOS; полные файлы поэтому содержат 8 029 init, 1 929 stuck и 14 095 CPM daily. Разделение по времени и pixel name воспроизводит release_cutover_daily.tsv, полный день сходится с inventory.tsv и release_cpm_daily_trends.tsv. Включать debug.web.extension.reload.failed.daily в сумму CPM нельзя: это отдельное семейство операций Web Extensions. Внутри CPM initialization.failed.after.extension.reload.daily и messaging.extension.reload.failed.daily обычно посылаются вместе на одной неудачной post-reload проверке: их суммы не обозначают разные эпизоды. .daily ограничен одним событием на имя пикселя за UTC-день на установку; разные имена могут относиться к одному пользователю и эпизоду. Переход версии внутри дня тоже меняет наблюдаемые суммы. Здесь нет числа уникальных пользователей, DAU той же версии и идентификатора для связывания событий.

Публикация release tag состоялась 5 октября в 15:18 UTC для iOS 7.240 и 09:46 UTC для macOS 1.210. Время после tag — доступная граница, не доказательство public-канала у каждого отправителя: пиксель не содержит channel/rollout cohort, и internal testing могло продолжаться после публикации.

До публикации release tag: отдельный срез

В пределах выгрузки за 5 октября до публикации iOS tag нет CPM daily событий версии 7.240. До публикации macOS tag у версии 1.210 есть 28 init failure.daily, 2 stuck.daily, 2 post-reload failed.daily, 7 recovered.without.reload.daily, 0 recovered.after.reload.daily — всего 39 CPM daily. В этих 28 init: 12 native snapshot без видимой ошибки, 7 background state, 5 только context error history, 3 tab attachment/injection (2 без scripts/zero views и 1 tab-not-in-context), 1 с неполными tab facts. В двух stuck нет отсутствующих scripts или controller mismatch. debug.web.extension.reload.failed.daily до tag нет. Более ранние internal-testing данные 28 сентября – 4 октября сохранены в cpm-web-extension-breakage-validation как архив и не смешиваются с таблицами после публикации.

2. Первичный сигнал: группы и события рядом с init failure.daily

Каждая строка попадает ровно в одну диагностическую группу по приоритету: tab scripts/controller → явные признаки background → история ошибок → неполные поля → видимо исправный native snapshot. Это классификация снимка, а не доказательство первопричины. Полные пересекающиеся признаки сохранены отдельно.

После release tag: диагностическая группа iOS init, из 6 624 macOS init, из 1 377 iOS stuck, из 1 440 macOS stuck, из 487
Native snapshot без видимой ошибки 3 717 (56,1%) 911 (66,2%) 789 (54,8%) 335 (68,8%)
Tab attachment / injection 931 (14,1%) 116 (8,4%) 53 (3,7%) 38 (7,8%)
Background state 768 (11,6%) 158 (11,5%) 457 (31,7%) 35 (7,2%)
Только история ошибок context 343 (5,2%) 158 (11,5%) 87 (6,0%) 79 (16,2%)
Недостаточно tab facts 865 (13,1%) 34 (2,5%) 54 (3,8%) 0

Контроль групп после tag: iOS init 3717+931+768+343+865=6624; macOS init 911+116+158+158+34=1377; iOS stuck 789+53+457+87+54=1440; macOS stuck 335+38+35+79=487. Контроль причин первого сбоя: iOS other 4803 + session.restoration 952 + extension.reload 670 + tab.crash 199 = 6624; macOS 1050+68+232+27=1377. Это reason навигации/эпизода, не причина поломки.

Окружающие события по главным цепочкам:

  1. iOS session restoration, 952. У 604 (63,4%) tab_controller_match=true, scripts отсутствуют, bg_view_creations=0; у 607 хвост bg_events содержит только load, ещё у 283 — load → view → proxy_on. 754 первых сбоя попали в bucket первых 30 секунд запуска. Код ожидает начальный loadAndSync и загрузку background content перед первой HTTP(S)-навигацией restored tab, но общий дедлайн ожидания — 5 секунд; неоконченная загрузка и более позднее внедрение script всё ещё способны дать временный timeout. 260 снимков уже выглядят исправно и требуют timings сообщения, а не ещё одного снимка состояния.
  2. iOS other, 4 803. 2 921 выглядят исправно; 831 имеют неполные tab facts; 334 содержат background load error code 6; 239 — scripts отсутствуют при нулевом числе background views. Частые хвосты load → view → proxy_on (1 450) и load → view → proxy_on → dealloc → view → proxy_on (934). dealloc фиксирует освобождение background view, не падение процесса; только 85 первичных iOS строк имеют явный died_* в доступном хвосте.
  3. Повторная проверка после extension reload, iOS 670 / macOS 232. Это именно первый CPM init timeout после reload, вместе с messaging.extension.reload.failed.daily. Типичный хвост iOS load → base_url_changed → view → proxy_on (483); macOS load → base_url_changed → view → proxy_on → dealloc → view → proxy_on (87). base_url_changed здесь совпадает с reload и сам по себе не доказывает ошибку URL. Native snapshot уже выглядит исправно у 470 iOS / 125 macOS; причина отсутствия ответа там не локализована.
  4. macOS other, 1 050. 713 выглядят исправно, 132 не имеют живого background view, 110 имеют только историческую context error, 47 — неверный controller без scripts. За все причины init неверный controller без scripts есть у 77/1 377 после tag и 0/28 до tag; в stuck — 35/487 после tag и 0/2 до tag. Init-сигнатура встречается с 10:34 до 23:21 UTC, а не только сразу после публикации в 09:46. Из 77 после tag 45 имеют app_version_change=updated. App update сам по себе не сохраняет старый WKWebView; эти строки не доказывают сценарий «вкладка осталась у старого контроллера после обновления». Требуется событие смены manager/controller при живой вкладке.
  5. iOS tab.crash, 199. 47 имеют code 6, 37 — явную смерть background процесса, 35 — scripts отсутствуют и background view не создан. Название reason означает навигацию после crash вкладки, а не установленную смерть CPM worker.

Вторичный stuck сдвигает iOS-картину: background state 768/6 624 (11,6%) на первом сбое против 457/1 440 (31,7%) на stuck; no-scripts/zero-view 917/6 624 против 52/1 440. Это согласуется с временными startup misses и более устойчивой background-проблемой, но это не переходная вероятность: имена .daily считаются независимо. У iOS code 6 находится в 364 stuck снимках (в 363 dealloc раньше первой ошибки); WebKit регистрирует code 6 как BackgroundContentFailedToLoad после неудачной загрузки service worker. Причина отказа регистрации из пикселя неизвестна. Хвост bg_events ограничен 12 событиями и может обрезать старые события.

Проверка по коду: что означает «исправный native-снимок»

  1. Пиксель измеряет отсутствие отдельного native-вызова. После navigationDidFinish при наличии context (или после lifecycle loaded) monitor ждёт до 4 секунд dashboardResponse, который поступает только из AutoconsentWebExtensionMessageHandler.handleRefreshCpmDashboardState при вызове refreshCpmDashboardState. Если на navigationDidFinish extension отсутствует, действует отдельное 30-секундное ожидание с отменой измерения. По истечении 4-секундного таймера reportFailure собирает снимок на тот момент. isAutoconsentExtensionLoaded проверяет наличие embedded context в controller, не готовность CPM JS.
  2. context_loaded=true не означает завершённый startup. В просмотренном WebKit_sparse isLoaded() означает наличие m_extensionController; он назначается до асинхронного moveLocalStorageIfNeeded, создания background view, регистрации scripts и addInjectedContent(). bg_view_alive=true означает живой WKWebView, а bg_process_responsive=true — что WebKit не признал его зависшим; это не проверка выполненного service worker listener. tab_has_ext_scripts=true проверяет список зарегистрированных WKUserScript, но не их выполнение в текущем документе. handler_registered=true проверяет запись в native router, но не факт обработки сообщения.
  3. initResp и наблюдаемый monitor сигнал расходятся в release bundle. Content script отправляет init в background. В успешной ветке background делает updateCpmDashboardState(...).then(refreshDashboardState(...)) без await, затем отдельно вызывает chrome.tabs.sendMessage(..., {type: "initResp"}). В ветках config_unavailable, settings_missing, setting_disabled, site_disabled он отправляет dashboard refresh и возвращается без initResp. Значит, init failure.daily возможен даже после отправки initResp, если dashboard refresh задержался или не сопоставился с документом; обратное тоже возможно: успешный health-сигнал без initResp.
  4. Есть конкретные места задержки и ложной атрибуции. Background перед успешной веткой ждёт remote config и native setting/site checks; native request timeout в bundled JS — 20 секунд против 4-секундного окна monitor. Обновление dashboard state проходит через последовательную async-очередь и session storage. Monitor сопоставляет URL refresh с текущим документом по scheme/host/port/path/query; несоответствие или опоздание оставит timeout даже при работающем JS. Сколько случаев пришло из каждого участка, текущие пиксели не показывают.

Эта проверка проведена именно на bundle из release tags 1.210.0+macos и 7.240.0+ios (zip-файлы совпадают); текущий main уже содержит другой bundle. Приоритет следующей telemetry — отдельные времена content init sent, background init received, initResp sent/received, dashboard refresh sent/received и результат сопоставления URL.

3. Session restoration: ушли ли временные сбои?

Нет. После release tag есть 952 iOS и 68 macOS первых session.restoration failures. Соответствующий поздний stuck.session.restoration.daily встречается 118 / 8 раз, но без связи событий нельзя сказать, какие именно первые сбои восстановились. recovered.without.extension.reload.daily (1 555 iOS / 346 macOS) не содержит reason, поэтому доля временных session-restoration эпизодов также неизвестна.

Сравнение по имени пикселя на одинаковых пятидневных окнах после предыдущих release tags: iOS 7.238 (23–27 сентября) — 3 372 386 session restoration из 5 821 858 init daily (57,9%); iOS 7.239 (30 сентября – 4 октября) — 3 014 131 из 5 390 550 (55,9%). У iOS 7.240 за первый неполный день — 952 из 6 624 (14,4%). Это сильное изменение состава сигналов, совместимое с readiness gate, вошедшим в 7.240, но не оценка снижения риска на пользователя: новая версия имеет иной ранний cohort и нет DAU. macOS 1.208 (23–27 сентября) — 4 531/76 336 (5,94%); 1.209 (30 сентября – 4 октября) — 7 425/114 075 (6,51%); 1.210 после публикации — 68/1 377 (4,94%). На macOS явного снижения по этому proxy пока нет. Gate входит в macOS 1.210 / iOS 7.240 и по умолчанию включён, но фактическое состояние remote flag у отправителей не передано.

4. Исправления tab lifecycle: виден ли эффект?

M1 tab identity fix вошёл в macOS 1.209, а в 1.208 его нет; PR менял только macOS. Старые версии не посылали новые поля controller/scripts, поэтому сравним лишь общий proxy stuck.other.daily / initialization.failed.after.other.daily, не частоту tab bugs. В сопоставимых пятидневных окнах он равен 27 493/69 565 = 39,52% на macOS 1.208 и 40 030/103 135 = 38,81% на 1.209. Изменение на 0,71 процентного пункта мало и может отражать состав cohort/нагрузки; это не измеренный эффект фикса. Новый 1.210 после публикации даёт 418/1 050 = 39,81%. Следовательно, по агрегатному тренду исчезновение tab breakage не подтверждено и не опровергнуто; именно относящиеся к нему события старых версий нельзя выделить без attribution.

5. After-stuck recovery mitigation: работает ли?

Узкий функциональный сигнал есть. M4 входит в macOS 1.210 / iOS 7.240 и при подтверждённом hang пытается reload embedded extension (remote flag по умолчанию enabled). recovered.after.extension.reload.daily означает, что после reload текущего поколения снова поступил и был сопоставлен native dashboard refresh; получение initResp content script этот пиксель не проверяет. После публикации таких событий от messaging_stuck — 916 iOS / 354 macOS. Все recovered.after вместе дают 963/1 440 = 66,9% от числа stuck daily на iOS и 362/487 = 74,3% на macOS, тогда как в предшествующих пятидневных окнах число пикселей этого имени относительно stuck daily составляло 3,23% (iOS 7.239) и 2,70% (macOS 1.209). Это большой скачок, согласующийся с автоматическим reload. Эти отношения не success rate: имена пикселей независимо throttled, эпизоды не соединены, одни установки могли дать несколько разных сигналов.

Ограничение эффекта: после публикации первый post-reload CPM probe всё ещё завершился timeout 670 раз на iOS и 232 на macOS, поэтому reload не гарантирует немедленного восстановления даже измеряемого native-вызова. Это не сбой самого API reload. Отдельный debug.web.extension.reload.failed.daily после публикации содержит один macOS error для embedded / cpm_messaging_hung / load и 223 iOS errors для другого adBlocking / scriptlet_update / unload extension; до публикации этих operation errors нет. На текущих данных M4 восстанавливает измеряемый background → native путь у части установок; нельзя вычислить долю stuck-эпизодов с полноценным initResp и CPM-функцией, которые остались невосстановленными, или изменение общей частоты init failures.

6. Другие CPM / Web Extension пиксели: что реально видно в системе

Сверка сделана по тем же версиям, полному UTC-дню 5 октября и с разделением по времени release tag. Полный наблюдаемый перечень autoconsent и web.extension с pixel_id, именем, platform suffix, частотой и числом записей — related_pixels.tsv (329 сгруппированных строк, включая отдельный pre-tag срез). autoconsent_sources.tsv делит каждый daily-пиксель по fromExtension=1, 0 и отсутствующему параметру; autoconsent_summary.tsv делает то же для standard summary и раскрывает счётчики событий внутри него. В таблице ниже только после release tag; записи до tag остаются в TSV отдельно.

Сигнал после tag iOS 7.240 macOS 1.210 Что он проверяет
autoconsent_init.daily, только fromExtension=1 56 906 2 825 Background Web Extension получил init, дошёл до разрешённой ветки CPM и отправил native pixel. Это происходит до отдельной попытки chrome.tabs.sendMessage(initResp) и не подтверждает доставку ответа.
autoconsent_summary, только fromExtension=1 324 549 standard-отчётов; 1 760 177 накопленных init 54 421 отчёт; 213 878 init Фоновый скрипт накопил события и позже отправил сводку через native. Это наблюдение многих успешных background→native проходов, но не denominator для init failure.daily: другое окно, другой тип частоты, эпизоды не соединены.
web_extension_loaded.daily 61 902 2 870 Manager загрузил хотя бы одно extension; имя не указывает, что это CPM, и ничего не говорит о конкретной вкладке.
web_extension_state_checked.daily 62 004 2 805 Lifecycle coordinator проверил набор ожидаемых/загруженных extension в manager.
web_extension_embedded_not_loaded.daily 3 389 1 Во время хотя бы одной проверки embedded extension ожидался, но отсутствовал в manager. Не проверяет controller/scripts конкретной вкладки.
web_extension_load_error.daily 4 4 Ошибка общей загрузки extension. Это отдельный сигнал от CPM timeout; по одному имени тип extension не известен.

Почему autoconsent_init нужно делить по источнику. Одинаковое имя пикселя используют Web Extension и старый Autoconsent user script. Всего init.daily после tag пришло 60 720 на iOS и 3 351 на macOS; из них fromExtension=1 — 56 906/2 825, fromExtension=0 — 1 100/1, без параметра — 2 714/525. В release-коде user script ставит 0 только при доступном Web Extensions API, но недоступном autoconsent extension; отсутствие параметра также не доказывает работу extension. .daily ограничен по общему имени, поэтому нельзя считать этот split долей всех init-вызовов. Standard summary не имеет такого daily throttle: extension-источник дал 324 549/54 421 сводок с init счётчиками, но сводка запускается двухминутным alarm и может прийти существенно позже навигации.

Функциональные CPM-события тоже есть: с fromExtension=1 после tag получены autoconsent_popup-found.daily 31 363 iOS / 1 918 macOS и autoconsent_done.daily 23 050 / 1 578; disabled-for-site.daily 4 763 / 694. Они показывают, что Web Extension действительно обнаруживает и обрабатывает popup на части навигаций. Ошибки error_optout.daily 513/107 и error_reload-loop.daily 280/49 относятся к обработке popup, а не к доставке initResp. self-test-fail.daily 153/97 не имеет fromExtension=1 в этих данных и потому не служит сигналом ошибки extension. Все эти имена общие с legacy user script, поэтому исходный fromExtension обязателен.

Lifecycle и соседние семейства: web_extension_embedded_installed.daily 51 958/1 756 и embedded_upgraded.daily 804/741 отражают операции установки, а не исполнение content script. Есть отдельные пиксели install/uninstall, ad-blocking, dark-reader, scriptlet fetch/validation/install и web_extension_ad_blocking_not_loaded; полный набор реально поступивших имён и чисел в related_pixels.tsv. Они полезны для общей работоспособности Web Extensions, но не локализуют CPM init-timeout. Все debug CPM health-пиксели и actual web_extension_reload_failed разобраны выше в разделах 1–5.

Вывод для крупнейшей группы init failure: в совокупности данные подтверждают, что Web Extension широко запускается и обрабатывает CPM на этих билдах. Они не подтверждают, что в 3 717 iOS / 911 macOS строках с исправным native-снимком background получил именно тот init, отправил initResp и content script его принял. Нет event/pixel для content init sent, background init received с общим navigation ID, initResp sent/received, начала/результата refreshCpmDashboardState или исхода сопоставления URL. Сопоставить autoconsent_init/summary с конкретным initialization.failed по текущей анонимной телеметрии нельзя. На macOS лишь 1 общий embedded_not_loaded.daily при 77 init failures с controller mismatch без scripts: это согласуется с тем, что глобальный manager может быть исправен, пока отдельная вкладка прикреплена неверно.

Код release tags: WebExtensionPixelFiring.swift (семейства и частоты CPM); WebExtensionManager.swift (.loaded после общего load); WebExtensionLifecycleCoordinator.swift (stateChecked/embeddedNotLoaded); платформенные AutoconsentMessageHandlerDelegate (пересылка Web Extension пикселей); AutoconsentUserScript.swift (то же имя с fromExtension=0 или без параметра); release bundle background handleAutoConsentMessage, firePixel, sendSummaryPixel (init, initResp и двухминутная сводка).

7. Общие bg_events у init failure и последующего stuck

Кодовая связь сильнее совпадения строк. Внутри CPMMessagingHealthMonitor.reportFailure первый timeout создаёт Episode, а messaging.stuck отправляется только после ещё одного timeout проверки, начатой позже первого failure (для confirmation — не session-restoration). Episode живёт не более пяти минут. Имя stuck наследует failureReason первого timeout; диагностика stuck снимается с вкладки второго timeout. CPMMessagingDiagnosticsRecorder сохраняет общую историю background context между этими снимками и при каждом берёт последние 12 событий; первый failure не очищает её. Поэтому stuck.bg_events действительно может содержать события, случившиеся до первого init failure. Новый context или вытеснение старых событий обрывает это наблюдение.

Проверка на выгрузке после release tag. Для каждого stuck искался более ранний init failure той же платформы и с тем же reason в окне пяти минут. Требовалось точное совпадение порядка токенов bg_events без возрастных суффиксов и совместимость всех возрастных buckets после прибавления разницы timestamps (допуск ±30 с). Для сильного сигнала оставлены цепочки длиной не менее шести событий. Контроль: timestamps stuck сдвинуты на +10 и −10 минут внутри post-tag интервала; все прочие правила те же. Это тест обогащения совпадениями, не восстановление анонимного reporter ID. Время пикселя может отличаться от времени снимка из-за доставки.

После tag Stuck daily С цепочкой ≥6 Совпало с более ранним init Контроль +10 / −10 мин Ровно один кандидат в выгрузке
iOS 7.240 1 440 1 025 693 255 / 270 467
macOS 1.210 487 368 168 29 / 19 148

Иными словами, длинные цепочки у последующих stuck совпадают с цепочками более ранних init failures значительно чаще, чем при соседнем сдвинутом времени. Но «ровно один кандидат» означает один подходящий анонимный пиксель в этой выгрузке, а не доказанный один пользователь. .daily мог подавить настоящий первый пиксель, а часто встречающиеся цепочки способны совпасть у разных пользователей.

Какие группы дают эту связь:

Группа stuck после tag Stuck всего Длинная цепочка совпала Контроль +10 мин Уникальный кандидат с той же группой init
iOS, исправный native-снимок 789 437 199 249
iOS, background load error 6 338 152 20 142
macOS, исправный native-снимок 335 138 21 120
macOS, только история context error 79 20 6 14

Пример совместимой пары iOS с одним кандидатом: в init-хвосте после повторных dealloc→view→proxy_on стоит error_wkwebextensioncontexterrordomain:6@30s; 41 секунду спустя stuck содержит тот же порядок 12 токенов, а последний error уже помечен @2m. Это согласуется с одним сохраняющимся background-сбоем через два timeout, но без reporter/episode ID остаётся вероятностным сопоставлением. В группе с исправным native-снимком найдены аналогичные пары с тем же длинным load→view→proxy_on→dealloc→view→proxy_on... и более старшими age buckets на stuck: два timeout могут происходить без нового видимого WebKit lifecycle-события.

Метод намеренно слаб для коротких хвостов load и load→view→proxy_on, в том числе startup no scripts/no view и macOS controller mismatch: у 35 macOS stuck с неверным controller только 3 хвоста длиной ≥6, поэтому отсутствие длинного match здесь ничего не опровергает. Из этих таблиц нельзя вычислять вероятность перехода отдельного init failure в stuck: нет идентификатора установки или episode, а .daily дедуплицирует имена. Тем не менее сочетание state machine в коде и превышения над контролем подтверждает, что stuck-пиксели отражают повторные timeout-эпизоды, а не просто новое имя для одиночного init failure.

Воспроизведение: match_event_chains.py → chain_match_summary.tsv, chain_match_transitions.tsv в каталоге выгрузки. Исходные строки: initialization_daily.tsv и events_daily.tsv. Числа выше используют только after-tag строки; до публикации остаются отдельно.

Источники и воспроизведение сверки

Локальная выгрузка и код подсчёта: cpm-public-attribution-2026-10-06/ в /Users/admin/DuckDuckGo/apple-browsers.git. inventory.tsv — полный CPM daily/count перечень и actual reload errors; release_cutover_daily.tsv — все CPM daily и actual reload daily по обе стороны release-tag timestamp; initialization_daily.tsv и events_daily.tsv — PII-free строки attribution с точным timestamp; release_cutover_groups.tsv и release_cutover_reasons.tsv — группы и причины по обе стороны tag, воспроизводятся analyze_cutover.py; daily_groups_exclusive.tsv, daily_families.tsv, daily_reasons.tsv, daily_signatures.tsv — сводки полного дня, включая pre-tag; release_cpm_daily_trends.tsv — 982 строки дневных трендов шести версий. Код поведения: CPMMessagingHealthMonitor.swift (reportFailure, reportSuccess), WebExtensionManager.swift (onConfirmedHang, reloadEmbeddedExtensionAfterCPMMessagingHang), WebExtensionLifecycleCoordinator.swift (navigation gate), PixelKit.swift (лимит .daily по имени и UTC). Снимок законченного дня; для вывода о динамике incidence нужен следующий полный UTC-день новой версии и знаменатель активных установок той же версии.