--- tags: - cpm - ios - telemetry updated: '2026-10-30' status: analysis --- # CPM iOS: оставшиеся группы и следующий фокус — 30 октября 2026 Продолжение: [[cpm-ios-idle-wake-investigation-2026-10-30]] — browser actions, shipped app/extension/WebKit paths, проверка storage/state queue, публичные аналоги и конкретный telemetry proposal. Уточнение интерпретации M4: `reload_state=loaded` без квалифицирующего нового замера не доказывает провал messaging recovery; отдельно выделены `response_timed_out` и предложен post-recovery opportunity counter. Обновлён ClickHouse-срез и проверены актуальные PR. **Следующий основной фокус — потеря ответа после idle wake при уже готовом фоне; второй — старт с `pending` без текущей error 6. Отдельно остаётся непроверенный хвост error-6 history → replacement view → pending: его нельзя объявлять закрытым #7730.** Это выбор следующего расследования и исправления по наблюдаемым симптомам, а не доказанная причинная классификация. macOS в этом пересчёте не анализировалась. ## Данные и проверка Источник: Grafana ClickHouse datasource `dekdbd6bqq1hcd`, `metrics.pixels`, agent `ddg_ios`, pixel_id `web`, `web.extension.cpm.episode.{count,daily}.ios.{phone,tablet}`. Запрос episodes выполнен **30 октября 11:01:52 UTC / 17:01:52 Бишкек**. Проверка свежести: последние события — **10:50:01 UTC / 16:50:01 Бишкек**. Серверная timezone независимо проверена: `America/New_York`. Все даты ниже — `metrics.date`, то есть Eastern; 30 октября — незавершённый день, а не полный UTC-день. Выгружена последняя неделя, 23–30 октября. Основной анализ — **7.243.0, 26–29 октября**, отдельно последний завершённый день 29 октября и частичный 30 октября. 23–25 октября содержат только семь count-событий до публичного релиза и исключены из production-приоритетов. У 7.244.0 найдены лишь два count-события 29 октября; это не выборка эффекта сегодняшних фиксов. Различить public/internal traffic внутри версии по этим полям нельзя. Обработаны **404 222 агрегированные строки**. За 26–29 октября: **477 214 count-эпизодов**, **305 853 первых дневных отчёта**, **15 576 подтверждённых cross-tab no-response эпизодов**, **5 902 таких первых дневных отчёта**. Независимый SQL повторяет классификацию на сервере; второй контроль проверяет исходы без неё. Завершённые дни сошлись точно, проверены 336 значений групп по окнам и метрикам. На 30 октября последовательные запросы расходятся из-за продолжающейся загрузки событий, даже при ограничении event timestamp. Числа частичного дня привязаны к сохранённому export, а не представлены как неизменяемый snapshot базы. Определения: - `no_response`: `outcome=no_response_before_deadline`, окно около пяти активных минут. Это не доказательство вечной поломки. - Подтверждение: `repeat_failures=1/2+` или `reload_state≠none`. - Cross-tab: `tabs_affected=2/3+`, плюс no-response и подтверждение выше. - `count` — эпизоды. `daily` — первый завершившийся эпизод установки за день; это нижняя оценка тяжёлых случаев, а не «хотя бы один тяжёлый сбой за день». Сумма по дням — install-days, не уникальные пользователи недели. - Ответ закрывает эпизод, но не доказывает доставку initResp каждой ранее падавшей вкладке. Приоритет непересекающихся групп сохранён из предыдущего разбора: error 6 в текущем поле или истории → no view → нет scripts/controller mismatch → update <2 мин → idle wake → context load/baseURL change <2 мин → other. `@30s` означает возраст **меньше 30 секунд**, `@2m` — меньше двух минут. Возраст view дополнительно проверяется по `bg_view_age`. ## Последний полный день: 29 октября Всего **364 695 эпизодов**, из них **9 849 подтверждённых cross-tab no-response**; на daily-leg — **4 090** соответствующих первых дневных отчётов. Доли ниже — от этих 4 090 daily-отчётов; число эпизодов указано отдельно: - **Idle wake: 1 331 / 32,5%; 2 920 эпизодов.** - **Recent context load: 841 / 20,6%; 1 710 эпизодов.** - **Error 6, включая историю: 712 / 17,4%; 2 818 эпизодов.** - Extension updated: 559 / 13,7%; 571 эпизод. - No background view: 342 / 8,4%; 760 эпизодов. - Other: 305 / 7,5%; 1 070 эпизодов. - Tab disconnected/P6: 0 daily, 0 cross-tab эпизодов; 15 подтверждённых no-response эпизодов без cross-tab условия. Первые две группы дают **53,1%** таких daily-отчётов. Wake + other — **40,0%**, но это не доказанный объём одного механизма. На частичном 30 октября в сохранённом export: 106 436 эпизодов, 3 317 подтверждённых cross-tab no-response; 1 322 соответствующих daily-отчёта. Wake — 372 / 28,1%, recent load — 306 / 23,1%, error 6 — 224 / 16,9%. Это поддерживает порядок приоритетов, но внутридневные частоты с полным днём не сравниваются. ## 1. Idle wake: крупнейшая группа без отдельного целевого исправления Все следующие footprints относятся к **2 920 cross-tab подтверждённым no-response count-эпизодам 29 октября**. Форма: `dealloc → view → proxy_on`, часто несколько циклов. У **2 688 / 92,1%** `bg_ready_after=under_1s`; у **2 774 / 95,0%** все восемь native-флагов true. Это делает «просто долго грузился background» слабым объяснением основной части этой группы. Native readiness не проверяет listener и доставку конкретного init/ответа. **660 / 22,6%** имеют только повторяющиеся `dealloc>view>proxy_on` в доступной истории, без load, origin change, update, interruption, died или error. Это видимый минимум немаркированного ядра; в **2 038 / 69,8%** всей wake-группы история достигает 12 токенов, поэтому отсутствие старого события ничего не доказывает. В истории `died_client` есть у 420 / 14,4%, `died_crash` — у 72 / 2,5%; ни один из них не объясняет большинство. `interruption` в истории встречается у 1 660, но `interrupted=true` самого первого замера — лишь у 50: это разные признаки. У 776 после M4 зафиксирован `reload_state=response_timed_out`; смена контекста сама по себе не гарантировала ответ. **Что исследовать для следующего фикса:** путь первого init после idle/resume при background-ready <1 s: дошёл ли init в worker, завершились ли native вызовы, был ли dashboard response и почему он не атрибутировался. Затем — bounded retry/re-init или другая recovery только для воспроизведённого разрыва. Простые длинные idle-тесты ранее были чистыми; повторять только их недостаточно. Нужен сценарий iOS resume/navigation и совпадение footprint. 1 275 из этих эпизодов на OS <26.6; stable-origin policy там не применяется. Но и на 26.6+ wake не становится автоматически покрытым P3. ## 2. Старт остаётся отдельным крупным кандидатом; recent load нельзя целиком вычесть как P3 Из 1 710 cross-tab эпизодов recent load **1 241 без `base_url_changed` в истории**, и **1 065 из них с текущим background `pending`**. На daily-leg соответствующий pending-поднабор — **585** первых дневных тяжёлых отчётов. Типичная короткая история: `load@30s,view@30s,proxy_on@30s`. У всей recent-load группы только 463 эпизода уже имели readiness <1 s. P3 устраняет подтверждённые задержки очистки данных при смене origin; эти симптомы могут частично улучшиться. Однако **recent load не является причинной меткой P3**, а отсутствие `base_url_changed` не исключает origin cleanup при первом контексте процесса: token сравнивает контексты только внутри текущего процесса. Следующая проверка после rollout P3 — pending startup отдельно от ready/no-response, с OS <26.6 / 26.6+ и фактическим состоянием флага. P4 late-document recovery в известной конфигурации default OFF; `startup_response_missing` — detection, не применённое лечение. На 26–29 октября найдено 226 933 count detection-события, но без ключа связи с эпизодом это не размер исправляемой тяжёлой группы. ## 3. Весь error-6 cohort не закрывается PR #7730 29 октября из 2 818 cross-tab эпизодов этой группы: - **508** имеют текущую атрибутированную error 6 в `bg_load_error_after`. - **2 310** имеют error 6 только в истории. - **2 276 из этих 2 310** уже относятся к новому текущему view с readiness `pending`; daily-leg этого поднабора — **311**. - **1 929** имеют не меньше двух error-токенов в хвосте истории. Частый pattern: `dealloc → error_6 → view → proxy_on`, повторённый несколько раз. В коде создание нового view очищает текущую атрибуцию load error, но сохраняет lifecycle history. Поэтому broad error-6 group существенно шире «нынешний view упал с error 6». [#7730](https://github.com/duckduckgo/apple-browsers/pull/7730), OPEN, head `cf668e2938`: restart того же failed view, если он ещё удерживается; released view сохраняет P2 retry, replacement view намеренно не трогается. PR также исправляет deferred/cooldown scheduling и дедупликацию старых ошибок. **Остаток не доказанно закрыт, но и точный uncovered share из этих чисел не выводится:** нет identity failed/replacement view на момент принятия recovery-решения, событий после первого snapshot и связанного outcome treatment. Повторный error token в старом recorder не обязательно означает новую независимую ошибку. Нужен отдельный OFF/ON сценарий с released failed view → новый view → pending на точном #7730. Если он остаётся красным, следующий фикс относится к stalled replacement load, а не к ещё одному restart уже покрытого retained view. ## 4. Other и no-view Other: 1 070 cross-tab эпизодов; у 863 readiness <1 s. Часто это те же idle-циклы, но текущему view уже 30 s–2 min, поэтому жёсткая граница wake классификатора переносит их в other. Это возможное продолжение того же пути потери init; считать одинаковую причину установленной нельзя. No-view — **158 115 / 43,4% всех эпизодов 29 октября**, но **только 760 / 7,7%** тяжёлых cross-tab эпизодов. Для 151 232 / 95,6% no-view эпизодов зарегистрирован какой-либо последующий ответ. Группа смешивает свежий `load` без view и уже работавший фон после dealloc. Большой объём transient failures не делает её первой целью исправлений browser-wide no-response. ## Что уже учтено как покрытие - [#7753](https://github.com/duckduckgo/apple-browsers/pull/7753) MERGED в `release/ios/7.244.0`; фильтр error documents и итоговые OS/flag ограничения stable origin. Это merge в будущий релиз, не измеренное исправление текущего 7.243.0. P3 [#7493](https://github.com/duckduckgo/apple-browsers/pull/7493) уже merged; runtime effect зависит от версии, OS и включения stable-origin флага. - [#7767](https://github.com/duckduckgo/apple-browsers/pull/7767) OPEN, head `45593bbb4e`: CPM upgrade-before-load на запуске; private origin переносится только при допустимой policy и отсутствии живого старого контекста. Хорошее целевое покрытие launch-upgrade пути, но не всех событий `extension_updated`, всех runtime upgrades или всех startup hangs. - #7730 — retained failed view и scheduling, с ограничениями выше. - [#7784](https://github.com/duckduckgo/apple-browsers/pull/7784) — instrumentation времени navigation readiness; поведение CPM recovery не исправляет. - [#7385](https://github.com/duckduckgo/apple-browsers/pull/7385) — полезная идея init progress, но PR всё ещё stacked на закрытом #7384 и описывает прежний контракт. Это не готовое покрытие текущих episodes; перенос требует адаптации к действующей схеме и extension bundle. - P6 на iOS сейчас практически не влияет на cross-tab результат. Graveyard не обоснован этим wake-срезом. Production effect ни одного нового PR этим анализом не измерен. Широкие symptom cohorts нельзя вычесть из знаменателя как будто все входящие эпизоды уже исправлены. ## iOS error pages: уточнение к прежним заметкам В [[cpm-post-release-analysis-2026-10-27]] осталось утверждение, что iOS runtime не проверялся. Есть более свежая отдельная проверка 29 октября: реальный diagnostic app на iOS 26.5/27.0, DNS и connection-refused отменяли замер; SSL и phishing предупреждения получали CPM dashboard response; после idle также не было episodes/M4. Подробности: [iOS runtime report](/Users/admin/DuckDuckGo/apple-browsers.git/cpm-ios-error-page-verification-2026-10-29/REPORT.md). Это поддерживает отдельный iOS-анализ. Проверка была simulator/dev-build, не полный набор физических устройств и не доказательство отсутствия любых false positives. ## Рабочая последовательность 1. Завершить уже подготовленные #7730 и #7767 по их существующему scope. 2. **Новая основная ветка исправлений: iOS idle/resume → init delivery/response attribution при уже ready фоне.** Одновременно отделять совпадающий other. 3. **Второй трек: pending startup без текущей error 6**; измерить остаток после включённого P3 и воспроизвести потерянный первый документ, прежде чем менять late recovery. 4. **Параллельная проверка границы #7730:** historical error 6 → replacement pending. Расширять recovery только после совпадающего воспроизведения. 5. Для разграничения причин нужны init-stage evidence и события после первого failure. Нынешний `bg_events` — только snapshot начала эпизода, один phase, максимум 12 событий / 255 символов; он не показывает развитие сбоя и результат конкретного retry. ## Воспроизводимость Локальный каталог: `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-ios-groups-2026-10-30/`. - `episodes.sql/.tsv/.json` — агрегированная выгрузка, без install/session IDs и URL страниц. - `inventory`, `freshness`, `controls`, `group_verification` — SQL, raw responses и TSV контрольных запросов. - `denominators_26…30` — запросы отдельно по дням; единый пятидневный запрос превысил лимит 7B rows, после чего разбит на дни. - `treatments` — события readiness/recovery/detection; связанного episode outcome в них нет. - `summary.json`, `groups.csv` — разбивки по count/daily, окнам, состоянию, OS и footprints. - `analyze.py`, `verify.py`, `query.py` — разбор, независимая сверка и read-only runner. - `pr-*.json` — проверенный GitHub snapshot состава и scope PR. - `verification-result.json` — точное совпадение завершённых дней и отдельно drift текущего дня. Код приложения, remote config и PR не менялись; внешним участникам данные не отправлялись.